Hi, here is some code you wrote to help with parsing bank statements.  I'd like to make the following changes:i'd like to adapt the script to include other file input types and use the same output format. Can you create file input menu that prompts for either "Canada Helps", "EFTs", and "etransfers". For the Canada Helps file input format, the CSV has headers that say: DONOR FIRST NAME, DONOR LAST NAME, AMOUNT, DATE. For the EFTs file input format, the CSV has headers that say: File Number, Funding Account Template,Payee/Payer Name,Amount,Value Date,Bank Branch Account,Cross Reference, Long Name ,Short Name, Status, Reason, As of, Generated....the only columns relevant in the EFT file format at Payee/Payer Name, Amount, and Value date. The payee/payer name will need to be split out firstname and last name using logic similar to what you have written. Then the last file has some text at the top until it gets to the headers: Posted, Value Date, Description,Debit, Credit. In this file you should only pay attention to the Value Date, Description and Credit. In the Description field, I only want you to capture the name using the logic you previously created where it says Telephone/Online banking , INTERAC ETRNSFR AD RECV. ignore the other rows in the file. Please show me the whole code <!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Bank Statement Parser</title>
    <!-- Include Papa Parse CDN without integrity and crossorigin -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/PapaParse/5.4.1/papaparse.min.js"></script>
    <!-- Include Bootstrap for Styling (Optional) without integrity and crossorigin -->
    <link 
        href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" 
        rel="stylesheet">
    <style>
        body {
            padding: 20px;
        }
        .table-responsive {
            max-height: 500px;
            overflow-y: auto;
        }
        .exception-row {
            background-color: #f8d7da;
        }
        .fixed-header th {
            position: sticky;
            top: 0;
            background: #fff;
            z-index: 2;
        }
    </style>
</head>
<body>
    <div class="container">
        <h1 class="mb-4">Bank Statement Parser</h1>
        <div class="mb-3">
            <label for="csvFile" class="form-label">Upload CSV File:</label>
            <input class="form-control" type="file" id="csvFile" accept=".csv">
        </div>
        <div id="tableContainer" class="mb-3" style="display: none;">
            <h3>Parsed Data</h3>
            <div class="table-responsive">
                <table class="table table-bordered" id="dataTable">
                    <thead class="fixed-header">
                        <tr>
                            <th>#</th>
                            <th>First Name</th>
                            <th>Last Name</th>
                            <th>Date</th>
                            <th>Fund</th>
                            <th>Source</th>
                            <th>Amount</th>
                            <th>Method</th>
                            <th>Source Detail</th>
                            <th>Check Number</th>
                            <th>CC Last Four</th>
                            <th>Notes</th>
                            <th>Batch Number</th>
                            <th>ID</th>
                        </tr>
                    </thead>
                    <tbody id="dataBody">
                        <!-- Rows will be populated here -->
                    </tbody>
                </table>
            </div>
        </div>
        <button id="downloadBtn" class="btn btn-primary" style="display: none;">Download Output CSV</button>
    </div>

    <script>
        document.getElementById('csvFile').addEventListener('change', function(e) {
            const file = e.target.files[0];
            if (!file) {
                alert('No file selected.');
                return;
            }

            console.log('File selected:', file.name);

            Papa.parse(file, {
                header: true,
                skipEmptyLines: true,
                complete: function(results) {
                    console.log('Parsing completed. Data:', results.data);
                    processData(results.data);
                },
                error: function(err) {
                    console.error('Error parsing CSV file:', err);
                    alert('Error parsing CSV file: ' + err.message);
                }
            });
        });

        function processData(data) {
            if (!data || data.length === 0) {
                alert('No data found in CSV.');
                return;
            }

            // Log the headers to ensure they're correct
            const headers = Object.keys(data[0]);
            console.log('CSV Headers:', headers);

            // Check if necessary headers are present
            const requiredHeaders = ['Posted', 'Value Date', 'Description', 'Debit', 'Credit'];
            const missingHeaders = requiredHeaders.filter(header => !headers.includes(header));

            if (missingHeaders.length > 0) {
                alert('Missing required headers: ' + missingHeaders.join(', '));
                console.error('Missing required headers:', missingHeaders);
                return;
            }

            const dataBody = document.getElementById('dataBody');
            dataBody.innerHTML = ''; // Clear previous data

            data.forEach((row, index) => {
                const description = row['Description'] || '';
                const parsedName = parseName(description);
                const isException = !parsedName.success;

                // Create table row
                const tr = document.createElement('tr');
                if (isException) tr.classList.add('exception-row');

                // Row Number
                const tdNum = document.createElement('td');
                tdNum.textContent = index + 1;
                tr.appendChild(tdNum);

                // First Name
                const tdFirst = document.createElement('td');
                if (parsedName.success) {
                    tdFirst.textContent = parsedName.firstName;
                } else {
                    const inputFirst = document.createElement('input');
                    inputFirst.type = 'text';
                    inputFirst.className = 'form-control';
                    inputFirst.placeholder = 'First Name';
                    tdFirst.appendChild(inputFirst);
                }
                tr.appendChild(tdFirst);

                // Last Name
                const tdLast = document.createElement('td');
                if (parsedName.success) {
                    tdLast.textContent = parsedName.lastName;
                } else {
                    const inputLast = document.createElement('input');
                    inputLast.type = 'text';
                    inputLast.className = 'form-control';
                    inputLast.placeholder = 'Last Name';
                    tdLast.appendChild(inputLast);
                }
                tr.appendChild(tdLast);

                // Date
                const tdDate = document.createElement('td');
                tdDate.textContent = row['Value Date'] || '';
                tr.appendChild(tdDate);

                // Fund Dropdown
                const tdFund = document.createElement('td');
                const selectFund = document.createElement('select');
                selectFund.className = 'form-select';
                ['General', 'Youth', 'Benevolent', 'Stewardship', 'Ministry'].forEach(fund => {
                    const option = document.createElement('option');
                    option.value = fund;
                    option.textContent = fund;
                    selectFund.appendChild(option);
                });
                tdFund.appendChild(selectFund);
                tr.appendChild(tdFund);

                // Source Dropdown
                const tdSource = document.createElement('td');
                const selectSource = document.createElement('select');
                selectSource.className = 'form-select';
                ['ACH', 'Cash', 'Cheque', 'EFT'].forEach(source => {
                    const option = document.createElement('option');
                    option.value = source;
                    option.textContent = source;
                    selectSource.appendChild(option);
                });
                tdSource.appendChild(selectSource);
                tr.appendChild(tdSource);

                // Amount
                const tdAmount = document.createElement('td');
                const credit = parseFloat((row['Credit'] || '').replace(/[^0-9.-]+/g,"")) || 0;
                const debit = parseFloat((row['Debit'] || '').replace(/[^0-9.-]+/g,"")) || 0;
                const amount = credit - debit;
                tdAmount.textContent = amount.toFixed(2);
                tr.appendChild(tdAmount);

                // Method (Assuming 'Method' based on 'Credit' and 'Debit')
                const tdMethod = document.createElement('td');
                if (credit > 0) {
                    tdMethod.textContent = 'Credit';
                } else if (debit > 0) {
                    tdMethod.textContent = 'Debit';
                } else {
                    tdMethod.textContent = '';
                }
                tr.appendChild(tdMethod);

                // Source Detail
                const tdSourceDetail = document.createElement('td');
                tdSourceDetail.textContent = ''; // Empty as per requirement
                tr.appendChild(tdSourceDetail);

                // Check Number
                const tdCheckNumber = document.createElement('td');
                tdCheckNumber.textContent = ''; // Empty as per requirement
                tr.appendChild(tdCheckNumber);

                // CC Last Four
                const tdCCLastFour = document.createElement('td');
                tdCCLastFour.textContent = ''; // Empty as per requirement
                tr.appendChild(tdCCLastFour);

                // Notes
                const tdNotes = document.createElement('td');
                tdNotes.textContent = ''; // Empty as per requirement
                tr.appendChild(tdNotes);

                // Batch Number
                const tdBatch = document.createElement('td');
                tdBatch.textContent = ''; // Empty as per requirement
                tr.appendChild(tdBatch);

                // ID
                const tdID = document.createElement('td');
                tdID.textContent = ''; // Empty as per requirement
                tr.appendChild(tdID);

                dataBody.appendChild(tr);
            });

            document.getElementById('tableContainer').style.display = 'block';
            document.getElementById('downloadBtn').style.display = 'block';
        }

        function parseName(description) {
            // Example Description: "Telephone/Online banking, INTERAC ETRNSFR AD RECVD JOHN DOE"
            // Adjust the parsing logic based on actual description patterns

            // First, check if 'INTERAC ETRNSFR AD RECVD' is present
            const keyword = 'INTERAC ETRNSFR AD RECVD';
            const keywordIndex = description.indexOf(keyword);

            if (keywordIndex === -1) {
                console.warn('Keyword not found in Description:', description);
                return { success: false };
            }

            const namePart = description.substring(keywordIndex + keyword.length).trim();

            if (!namePart) {
                console.warn('No name found after keyword in Description:', description);
                return { success: false };
            }

            console.log('Extracted name part:', namePart);

            // Define regex patterns for different name formats
            const patterns = [
                // Firstname Lastname
                /^([A-Za-z\-]+)\s+([A-Za-z\-]+)$/,
                // Firstname M. Lastname
                /^([A-Za-z\-]+)\s+[A-Za-z]\.\s+([A-Za-z\-]+)$/,
                // Firstname Middlename Lastname
                /^([A-Za-z\-]+)\s+[A-Za-z]+\s+([A-Za-z\-]+)$/,
                // Firstname Middleinitial Lastname (without dot)
                /^([A-Za-z\-]+)\s+[A-Za-z]\s+([A-Za-z\-]+)$/
            ];

            for (let pattern of patterns) {
                const match = namePart.match(pattern);
                if (match) {
                    let firstName = match[1];
                    let lastName = match[2];

                    console.log('Parsed Name:', firstName, lastName);
                    return {
                        success: true,
                        firstName: firstName,
                        lastName: lastName
                    };
                }
            }

            // If none of the patterns match, return failure
            console.warn('Name format unrecognized:', namePart);
            return { success: false };
        }

        document.getElementById('downloadBtn').addEventListener('click', function() {
            const table = document.getElementById('dataTable');
            const rows = table.querySelectorAll('tr');
            const output = [];

            // Define the headers for the output CSV
            const headers = ["First Name","Last Name","","Date","Fund","Fund Number","Amount","Method","Source","Check Number","CC Last Four","Notes","Batch Number","ID"];
            output.push(headers);

            // Iterate over table rows
            for (let i = 1; i < rows.length; i++) { // Start from 1 to skip header
                const cols = rows[i].querySelectorAll('td');
                const rowData = [];

                // First Name
                const firstNameInput = cols[1].querySelector('input');
                const firstName = firstNameInput ? firstNameInput.value.trim() : cols[1].textContent.trim();
                rowData.push(firstName);

                // Last Name
                const lastNameInput = cols[2].querySelector('input');
                const lastName = lastNameInput ? lastNameInput.value.trim() : cols[2].textContent.trim();
                rowData.push(lastName);

                rowData.push(""); // Empty column for third field

                // Date
                rowData.push(cols[3].textContent.trim());

                // Fund
                const fundSelect = cols[4].querySelector('select');
                const fund = fundSelect ? fundSelect.value : '';
                rowData.push(fund);

                rowData.push(""); // Fund Number

                // Amount
                rowData.push(cols[6].textContent.trim());

                // Method
                rowData.push(cols[7].textContent.trim());

                // Source
                const sourceSelect = cols[5].querySelector('select');
                const source = sourceSelect ? sourceSelect.value : '';
                rowData.push(source);

                // Check Number
                rowData.push(cols[8].textContent.trim());

                // CC Last Four
                rowData.push(cols[9].textContent.trim());

                // Notes
                rowData.push(cols[10].textContent.trim());

                // Batch Number
                rowData.push(cols[11].textContent.trim());

                // ID
                rowData.push(cols[12].textContent.trim());

                output.push(rowData);
            }

            // Convert to CSV
            const csv = Papa.unparse(output);

            // Create a blob and download link
            const blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' });
            const url = URL.createObjectURL(blob);
            const a = document.createElement('a');
            a.href = url;
            a.download = 'output.csv';
            a.click();
            URL.revokeObjectURL(url);
        });
    </script>
</body>
</html>