COD label Generation side by side

I have developed HTML, CSS, and JavaScript code that allows an Excel file to be uploaded and generates COD labels for pasting on articles.

My code is working fine and is successfully generating the COD labels.

However, the issue is that I want to develop the option for two COD labels side by side on one line. User provision has been added in UI but I failed to develop the functionality in the generated label.

I have tried to find a solution on Google and StackOverflow but I failed.

<script src="https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.17.0/xlsx.full.min.js"></script>
<script src="https://unpkg.com/bwip-js"></script>

<h1>Label Generator</h1>

<form id="uploadForm" enctype="multipart/form-data">
  <div style="text-align: center; margin-bottom: 20px;">
    <a href="https://drive.google.com/uc?export=download&id=11CkMhmu0YQEBtBopzMRe0m0fB2qGGIhJ" target="_blank">Download Format Excel File</a>
  </div>
  <div style="display: flex; gap: 16px;">
    <div style="flex: 1;">
      <label for="excelFile">Upload Excel file:</label>
    </div>
    <div style="flex: 1;">
      <input type="file" name="excelFile" id="excelFile" accept=".xlsx, .xls" required>
    </div>
  </div>
  <div style="display: flex; gap: 16px;">
    <div style="flex: 1;">
      <label for="labelHeight">Height of label (in mm):</label>
      <input type="number" name="labelHeight" id="labelHeight" min="1" value="105" required>
    </div>
    <div style="flex: 1;">
      <label for="widthforlable">Width of Label (in mm)</label>
      <input type="number" name="width" id="width" step="0.1" min="0" value="100" required>
    </div>
  </div>
  <div style="display: flex; gap: 16px;">
    <div style="flex: 1;">
      <label for="fontStyle">Font Style:</label>
      <input type="text" name="fontStyle" id="fontStyle" value="Arial" required>
    </div>
    <div style="flex: 1;">
      <label for="fontSize">Font Size (in px):</label>
      <input type="number" name="fontSize" id="fontSize" min="1" value="14" required>
    </div>
  </div>
  <div style="display: flex; gap: 16px;">
    <div style="flex: 1;">
      <label for="barcodeHeight">Barcode Height:</label>
      <input type="number" name="barcodeHeight" id="barcodeHeight" min="1" value="6" required>
    </div>
    <div style="flex: 1;">
      <label for="rowsPerPage">Rows per Page:</label>
      <input type="number" name="rowsPerPage" id="rowsPerPage" min="1" max="2" value="2" oninput="validity.valid||(value='')" required>
    </div>

    <div style="flex: 1;">
      <label for="labelsSideBySide">Labels in a row:</label>
      <input type="number" name="labelsSideBySide" id="labelsSideBySide" min="1" max="2" value="2" oninput="validity.valid||(value='')" required>
    </div>
  </div>
  <div style="display: flex; gap: 16px;">
    <div style="flex: 1;">
      <label for="BookingOffice">Booking Office:</label>
      <input type="text" name="BookingOffice" id="BookingOffice" required>
    </div>
    <div style="flex: 1; display: flex; flex-direction: column; align-items: flex-start;">
      <label for="senderName">Sender Name:</label>
      <input type="text" name="senderName" id="senderName" required>
    </div>
  </div>
  <div style="display: flex; gap: 16px;">
    <div style="flex: 1;">
      <label for="address1">Sender Address1:</label>
      <input type="text" name="address1" id="address1" required>
    </div>
    <div style="flex: 1;">
      <label for="address2">Sender Address2:</label>
      <input type="text" name="address2" id="address2">
    </div>
  </div>
  <div style="display: flex; gap: 16px;">
    <div style="flex: 1;">
      <label for="city">City and Pincode:</label>
      <input type="text" name="city" id="city" required>
    </div>
    <div style="flex: 1;">
      <label for="mobileNumber">Mobile Number:</label>
      <input type="tel" name="mobileNumber" id="mobileNumber" required>
    </div>
  </div>
  <div style="display: flex; gap: 16px;">
    <div style="flex: 1;">
      <label for="customerID">Customer ID:</label>
      <input type="text" name="customerID" id="customerID" required>
    </div>
    <div style="flex: 1;">
      <label for="billerID">Biller ID:</label>
      <input type="text" name="billerID" id="billerID" required>
    </div>
  </div>
  <div style="display: flex; gap: 16px;">
    <div style="flex: 1;">
      <button type="button" onclick="savePreferences()">Save Preferences</button>
    </div>
    <div style="flex: 1;">
      <button type="button" onclick="generateLabels()">Generate Labels</button>
    </div>
  </div>
</form>
const myForm = document.querySelector('#uploadForm');

window.onload = loadPreferences;

function savePreferences() {
  const preferences = {
    labelHeight: document.querySelector('#labelHeight').value,
    width: document.querySelector('#width').value,
    fontStyle: document.querySelector('#fontStyle').value,
    fontSize: document.querySelector('#fontSize').value,
    rowsPerPage: document.querySelector('#rowsPerPage').value,
    barcodeHeight: document.querySelector('#barcodeHeight').value,
    BookingOffice: document.querySelector('#BookingOffice').value,
    senderName: document.querySelector('#senderName').value,
    address1: document.querySelector('#address1').value,
    address2: document.querySelector('#address2').value,
    city: document.querySelector('#city').value,
    mobileNumber: document.querySelector('#mobileNumber').value,
    customerID: document.querySelector('#customerID').value,
    billerID: document.querySelector('#billerID').value,
  };

  localStorage.setItem('labelPreferences', JSON.stringify(preferences));
  alert('Preferences saved successfully!');
}


function loadPreferences() {
  const storedPreferences = localStorage.getItem('labelPreferences');

  if (storedPreferences) {
    const preferences = JSON.parse(storedPreferences);

    document.querySelector('#labelHeight').value = preferences.labelHeight;
    document.querySelector('#width').value = preferences.width;
    document.querySelector('#fontStyle').value = preferences.fontStyle;
    document.querySelector('#fontSize').value = preferences.fontSize;
    document.querySelector('#rowsPerPage').value = preferences.rowsPerPage;
    document.querySelector('#barcodeHeight').value = preferences.barcodeHeight;
    document.querySelector('#BookingOffice').value = preferences.BookingOffice;
    document.querySelector('#senderName').value = preferences.senderName;
    document.querySelector('#address1').value = preferences.address1;
    document.querySelector('#address2').value = preferences.address2;
    document.querySelector('#city').value = preferences.city;
    document.querySelector('#mobileNumber').value = preferences.mobileNumber;
    document.querySelector('#customerID').value = preferences.customerID;
    document.querySelector('#billerID').value = preferences.billerID;
  }
}


function generateLabels() {
  const fileInput = document.querySelector('input[name="excelFile"]');
  const widthInput = document.querySelector('#width');
  const labelHeightInput = document.querySelector('#labelHeight');
  const fontStyleInput = document.querySelector('#fontStyle');
  const fontSizeInput = document.querySelector('#fontSize');
  const rowsPerPageInput = document.querySelector('#rowsPerPage');
  const barcodeHeightInput = document.querySelector('#barcodeHeight');
  const BookingOfficeInput = document.querySelector('#BookingOffice');
  const senderNameInput = document.querySelector('#senderName');
  const address1Input = document.querySelector('#address1');
  const address2Input = document.querySelector('#address2');
  const cityInput = document.querySelector('#city');
  const mobileNumberInput = document.querySelector('#mobileNumber');
  const customerIDInput = document.querySelector('#customerID');
  const billerIDInput = document.querySelector('#billerID');
  const file = fileInput.files[0];
  const width = widthInput.value;
  const labelHeight = parseInt(labelHeightInput.value);
  const fontStyle = fontStyleInput.value;
  const fontSize = parseInt(fontSizeInput.value);
  const rowsPerPage = parseInt(rowsPerPageInput.value);
  const barcodeHeight = parseInt(barcodeHeightInput.value);
  const BookingOffice = BookingOfficeInput.value;
  const senderName = senderNameInput.value;
  const address1 = address1Input.value;
  const address2 = address2Input.value;
  const city = cityInput.value;
  const billerID = billerIDInput.value;
  const mobileNumber = mobileNumberInput.value;

  if (file && labelHeight) {
    const reader = new FileReader();

    reader.onload = function(e) {
      const excelData = e.target.result;
      const workbook = XLSX.read(excelData, {
        type: 'array'
      });
      const sheetName = workbook.SheetNames[0];
      const sheet = workbook.Sheets[sheetName];
      const data = XLSX.utils.sheet_to_json(sheet, {
        header: 1
      });
      const labels = processExcel(excelData, file, width, labelHeight, fontStyle, fontSize, rowsPerPage, barcodeHeight, BookingOffice, senderName, address1, address2, city, billerID, mobileNumber);

      const newWindow = window.open();
      newWindow.document.write(`
      <!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <style>
        
        .label {
            width: ${width}mm;      
            height: ${labelHeight}mm; 
            border: 2px solid #333; 
            padding: 20px; 
            font-family: ${fontStyle};                      
            position: relative;
            background-color: #fff; 
            box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); 
            line-height: normal;
            font-size: ${fontSize}px;
        }
        
        .label hr {
         width: 100%;
         border: 0;
         height: 1px;
         background: #333; /* Example color */
         margin: 10px 0; /* Example spacing */
         }
        
   .heading {
    text-align: center;
    font-weight: bold;
    margin-top: 0.1%; /* Adjust the margin from the top as needed */
    color: #333;
    font-size: ${fontSize}px;
}

        
        .details {
            text-align: left;
            margin-bottom: 10px; 
        }

        
        .barcode {
          position: absolute;
          top: 20%;
          right: 50%; /* Position the right edge at 50% of the parent's width */
          transform: translateX(50%); /* Move the element left by 50% of its own width */
         }
         
        
        .addressee {
    position: absolute;
    top: 35%;
    left: 60%;
    text-align: left;
    color: #555;
    white-space: normal; /* Allow text to wrap */
    line-height: 1;
    margin-bottom: 10px;
    font-family: ${fontStyle};
    font-size: ${fontSize}px;
    max-width: 40%; /* Set a maximum width for the addressee element */
    word-wrap: break-word; /* Allow long words to break and wrap */
    font-weight: bold; /* Make the sender text bold */
}

        
        
      .details-table {
       position: absolute;
       top: 54%;
       left: 2.5%;
       width: 50%;
       max-width: 200px;
       border-collapse: collapse;
       transform: translateY(-50%); /* Center the element vertically */
       }

        .details-table th, .details-table td {
            border: 2px solid #ddd;
            padding: 5px;
            text-align: left;
        }
        
        
     
.sender {
    position: absolute;
    bottom: 5px;
    left: 20px;
    text-align: left;
    color: #555;
    word-wrap: break-word; /* Allow long words to break and wrap */
    max-width: calc(100% - 40px); /* Set maximum width to the label width minus the left and right padding */
    font-family: ${fontStyle};
    font-size: ${fontSize};
    font-weight: bold; /* Make the sender text bold */
    line-height: 1;
}

.sender p {
    margin-bottom: 10px; /* Adjust the margin bottom as needed for proper spacing */
    line-height: 1.2; /* Adjust the line height as needed for better readability */
    word-wrap: break-word; /* Allow long words to break and wrap */
}

      
          
         @media print {
              .label-container:nth-child(${rowsPerPage}n) {
                page-break-after: always;
             } 
             
       } 
        
    </style>
</head>
<body>
     ${labels}
   
           
</body>
</html>`);
    };

    reader.readAsArrayBuffer(file);
  } else {
    alert('Please select an Excel file and enter a valid label height.');
  }
}


function convertAmountToWords(amount) {
  const units = ['', 'One', 'Two', 'Three', 'Four', 'Five', 'Six', 'Seven', 'Eight', 'Nine'];
  const teens = ['Ten', 'Eleven', 'Twelve', 'Thirteen', 'Fourteen', 'Fifteen', 'Sixteen', 'Seventeen', 'Eighteen', 'Nineteen'];
  const tens = ['', '', 'Twenty', 'Thirty', 'Forty', 'Fifty', 'Sixty', 'Seventy', 'Eighty', 'Ninety'];

  function convertLessThanOneThousand(num) {
    let result = '';

    if (num >= 100) {
      result += units[Math.floor(num / 100)] + ' Hundred ';
      num %= 100;
    }

    if (num >= 10 && num < 20) {
      result += teens[num - 10];
    } else {
      result += tens[Math.floor(num / 10)];
      if (num % 10 !== 0) {
        result += ' ' + units[num % 10];
      }
    }

    return result.trim();
  }

  function convertToWords(num) {
    if (num === 0) return 'Zero';

    const billion = Math.floor(num / 1000000000);
    const million = Math.floor((num % 1000000000) / 1000000);
    const thousand = Math.floor((num % 1000000) / 1000);
    const remainder = num % 1000;

    let result = '';

    if (billion > 0) result += convertLessThanOneThousand(billion) + ' Billion ';
    if (million > 0) result += convertLessThanOneThousand(million) + ' Million ';
    if (thousand > 0) result += convertLessThanOneThousand(thousand) + ' Thousand ';
    if (remainder > 0 || result === '') result += convertLessThanOneThousand(remainder);

    return result.trim();
  }

  const amountInWords = convertToWords(parseInt(amount));

  return amountInWords + ' Rupees Only';
}

function generateBarcodeImage(text) {
  const barcodeHeight = parseInt(document.querySelector('#barcodeHeight').value);
  const labelWidth = parseInt(document.querySelector('#width').value);

  const maxBarcodeWidth = 80; // Set the maximum barcode width in mm
  let barcodeWidth = labelWidth * 0.7; // 30% of label width

  if (barcodeWidth > maxBarcodeWidth) {
    barcodeWidth = maxBarcodeWidth; // Cap the width if it exceeds the maximum
  }


  if (text.trim() !== "") {
    const canvas = document.createElement('canvas');
    bwipjs.toCanvas(canvas, {
      bcid: 'code128',
      text: text,
      scale: 2,
      height: barcodeHeight,
      width: barcodeWidth,
      includetext: true,
      textxalign: 'center',
    });

    const img = document.createElement('img');
    img.src = canvas.toDataURL();
    img.alt = 'Barcode Image';
    img.className = 'barcode-image';

    return img.outerHTML;
  } else {

    return '<div style="height:' + barcodeHeight + 'px;"></div>';
  }
}

function processExcel(excelData, file, width, labelHeight, fontStyle, fontSize, rowsPerPage, barcodeHeight, BookingOffice, senderName, address1, address2, city, billerID, mobileNumber) {
  const workbook = XLSX.read(excelData, {
    type: 'array'
  });
  const sheetName = workbook.SheetNames[0];
  const sheet = workbook.Sheets[sheetName];
  const data = XLSX.utils.sheet_to_json(sheet, {
    header: 1
  });
  let labels = '';
  let labelsCounter = 0;
  let rowsCounter = 0;

  for (let i = 1; i < data.length; i++) {
    const row = data[i];
    const barcodeNumber = row[1] || '';

    const customerID = document.querySelector('#customerID').value;
    const billerID = document.querySelector('#billerID').value;

    let detailsTableRows = '';

    if (row[12]) {
      detailsTableRows += `
        <tr>
          <th>Weight</th>
          <td>${row[12]} gm</td>
        </tr>
      `;
    }

    if (row[13]) {
      detailsTableRows += `
        <tr>
          <th>COD Value</th>
          <td>Rs. ${row[13]}</td>
        </tr>
      `;
    }

    if (row[14]) {
      detailsTableRows += `
        <tr>
          <th>Ins. Value</th>
          <td>Rs. ${row[14]}</td>
        </tr>
      `;
    }

    if (customerID) {
      detailsTableRows += `
        <tr>
          <th>Customer ID</th>
          <td>${customerID}</td>
        </tr>
      `;
    }

    if (billerID) {
      detailsTableRows += `
        <tr>
          <th>Biller ID</th>
          <td>${billerID}</td>
        </tr>
      `;
    }

    // Conditionally include the amount in words based on label width
    let amountInWordsSection = '';
    if (width >= 200) {
      amountInWordsSection = `(${convertAmountToWords(row[13])})`;
    }

    const labelContent = `
      <div class="label-container" style="margin-bottom: 20px; font-size: ${fontSize};">
        <div class="label">
          <div class="heading">Cash On Delivery for Rs. ${row[13] ? row[13] : '-'} ${amountInWordsSection}</div>
          <div class="heading">Booked under BNPL Scheme at ${BookingOffice}</div> 
          <hr style="width: 100%; border: none; border-top: 1px solid #333; margin: 10px 0;">
          <div class="sender" style="font-family: ${fontStyle}; line-height: 0.5;">
            <hr style="width: ${width}mm; border: none; border-top: 1px solid #333; margin: 10px 0;">
            <p>
              From:-
              ${senderName ? `${senderName},` : ''}
              ${address1 ? `${address1},` : ''}
              ${address2 ? `${address2},` : ''}
              ${city ? `${city}` : ''}
              ${mobileNumber ? `Mo:- ${mobileNumber}` : ''}
            </p>
          </div>

          <div class="details">
            <table class="details-table">
              ${detailsTableRows}
            </table>
          </div>

          <div class="addressee" style="font-family: ${fontStyle}; font-size: ${fontSize}px; line-height: 1.5;">
            <div>To,</div>
            ${row[5] ? `<div>${row[5]},</div>` : ''}
            ${row[6] ? `<div>${row[6]},</div>` : ''}
            ${row[7] ? `<div>${row[7]},</div>` : ''}
            ${row[8] ? `<div>${row[8]},</div>` : ''}
            ${row[3] || row[4] ? `<div>${row[3] || ''} - ${row[4] || ''}</div>` : ''}
            ${row[10] ? `<div>Mo:- ${row[10]}</div>` : ''}
          </div>

          <div class="barcode">${generateBarcodeImage(barcodeNumber)}</div>
        </div>
      </div>
    `;

    labels += labelContent;
  }

  return labels;
}
body {
  font-family: 'Arial', sans-serif;
  background-color: #f4f4f4;
  margin: 0;
  padding: 20px;
}

h1 {
  text-align: center;
  color: #333;
}

form {
  max-width: 400px;
  margin: 20px auto;
  background-color: #fff;
  padding: 20px;
  border-radius: 8px;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
  line-height: 1.6;
}

input {
  width: 100%;
  padding: 8px;
  margin-bottom: 16px;
  box-sizing: border-box;
}

button {
  background-color: #4caf50;
  color: #fff;
  padding: 10px;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  display: block;
  width: 100%;
  line-height: 1.6;
}

button:hover {
  background-color: #45a049;
}