Hello,
I have a Google Apps Script that is designed to perform OCR on a PDF from Gmail and save the data to a Google Sheet.
The script consistently fails on the Drive.Files.copy() or Drive.Files.create() command with the error: Exception: Invalid argument.
The strange part is that when I run the exact same API call in a separate, isolated test function on a known file, it works perfectly. The failure only happens when the call is made inside the main function's loops.
We have already tried:
Rewriting forEach loops as standard for loops.
Forcing re-authorization of all scopes, including the drive scope.
Ensuring the Advanced Drive API service is enabled.
Verifying all parameters passed to the API call.
This seems like a platform bug or a strange execution context issue. Can anyone see what might be causing the API call to fail only when run inside the full script?
Here is the complete code, which includes the main failing function (processInvoices) and the successful diagnostic function (runFinalOcrTest).
// --- SCRIPT CONFIGURATION ---
// Using a placeholder email for privacy
var GMAIL_QUERY = 'from:ven...@example.com subject:"Invoice" has:attachment is:unread';
var FOLDER_NAME = 'Gmail Invoices';
/**
* Main function that fails.
*/
function processInvoices() {
var folders = DriveApp.getFoldersByName(FOLDER_NAME);
var folder = folders.hasNext() ? folders.next() : DriveApp.createFolder(FOLDER_NAME);
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
if (sheet.getRange("A1").getValue() === "") {
var headers = [
"Invoice Number", "Invoice Date", "Grand Total", "Buyer Name", "Buyer GSTIN",
"Contract No", "Delivery Order No", "Truck No", "HSN No", "Material",
"Quantity (MTS)", "Rate", "Gross Amount", "IGST Amount", "Cess Amount",
"TCS Amount", "Amount in Words", "IRN No", "File Name"
];
sheet.getRange(1, 1, 1, headers.length).setValues([headers]).setFontWeight("bold");
}
var threads = GmailApp.search(GMAIL_QUERY);
for (var i = 0; i < threads.length; i++) {
var messages = threads[i].getMessages();
for (var j = 0; j < messages.length; j++) {
var message = messages[j];
var attachments = message.getAttachments();
for (var k = 0; k < attachments.length; k++) {
var attachment = attachments[k];
if (attachment.getContentType() === 'application/pdf') {
var fileName = attachment.getName();
var pdfText;
try {
var originalPdfFile = folder.createFile(attachment);
var ocrOptions = { ocr: true, ocrLanguage: 'en' };
var copyResource = { name: 'temp_ocr_doc_for_' + fileName };
var ocrFile = Drive.Files.copy(copyResource, originalPdfFile.getId(), ocrOptions);
var doc = DocumentApp.openById(ocrFile.id);
pdfText = doc.getBody().getText();
Drive.Files.remove(ocrFile.id);
Logger.log('Successfully performed OCR on: ' + fileName);
} catch (e) {
Logger.log('Error during OCR processing for ' + fileName + ': ' + e.toString());
continue;
}
var details = extractAllDetailsFromPDF(pdfText);
if (details.invoiceNumber) {
sheet.appendRow([
details.invoiceNumber, details.invoiceDate, details.grandTotal, details.buyerName, details.buyerGstin,
details.contractNo, details.deliveryOrderNo, details.truckNo, details.hsnNo, details.material,
details.quantity, details.rate, details.grossAmount, details.igst, details.cess,
details.tcs, details.amountInWords, details.irnNo, fileName
]);
Logger.log('Successfully extracted details from ' + fileName);
} else {
Logger.log('Could not extract invoice number from ' + fileName + ' after OCR. Skipping.');
}
Utilities.sleep(1000);
}
}
message.markRead();
}
}
}
/**
* Diagnostic function that SUCCEEDS.
*/
function runFinalOcrTest() {
var fileId = 'PASTE_A_VALID_FILE_ID_HERE'; // Hardcoded ID of a saved PDF
var fileName = 'sample_invoice.pdf';
Logger.log('Starting final diagnostic test on a known file ID: ' + fileId);
try {
var ocrOptions = { ocr: true, ocrLanguage: 'en' };
var copyResource = { name: 'final_diagnostic_test_' + fileName };
var ocrFile = Drive.Files.copy(copyResource, fileId, ocrOptions);
Logger.log('SUCCESS: The API call worked.');
Drive.Files.remove(ocrFile.id);
} catch (e) {
Logger.log('ERROR: The API call failed. Error: ' + e);
}
}
/**
* The data extraction function (regex patterns).
*/
function extractAllDetailsFromPDF(text) {
var details = {
invoiceNumber: null, invoiceDate: null, grandTotal: null, buyerName: null, buyerGstin: null,
contractNo: null, deliveryOrderNo: null, truckNo: null, hsnNo: null, material: null,
quantity: null, rate: null, grossAmount: null, igst: null, cess: null,
tcs: null, amountInWords: null, irnNo: null
};
var match;
match = text.match(/Invoice No\.\s?\/\s?Date[^\d]*(\d{12})/i);
if (match) details.invoiceNumber = match[1];
match = text.match(/Invoice No\.\s?\/\s?Date[^\d]*\d{12}\/(\d{2}\.\d{2}\.\d{4})/i);
if (match) details.invoiceDate = match[1];
match = text.match(/INR\s+([\d,]+\.\d{2})/i);
if (match) details.grandTotal = parseFloat(match[1].replace(/,/g, ''));
match = text.match(/Buyer\s*\n(.*?)\n/i);
if (match) details.buyerName = match[1].trim();
match = text.match(/Buyer\s*(?:.|\n)*?GSTIN:(\S+)/i);
if (match) details.buyerGstin = match[1];
match = text.match(/Contract No\.\s?\/\s?Date.*:\s*(\d+)/i);
if (match) details.contractNo = match[1];
match = text.match(/Delivery Order No\.\s*:\s*(\d+)/i);
if (match) details.deliveryOrderNo = match[1];
match = text.match(/Truck No\/?RR No\s*:\s*(\S+)/i);
if (match) details.truckNo = match[1];
match = text.match(/HSN No\s*:\s*(\d+)/i);
if (match) details.hsnNo = match[1];
match = text.match(/Material Code Description\s*\n(.*?)\n/i);
if (match) details.material = match[1].trim();
match = text.match(/(\d+\.\d+)\s+MTS\s+[\d,]+\.\d{2}/i);
if (match) details.quantity = parseFloat(match[1]);
match = text.match(/\d+\.\d+\s+MTS\s+([\d,]+\.\d{2})/i);
if (match) details.rate = parseFloat(match[1].replace(/,/g, ''));
match = text.match(/Net Price\s+([\d,]+\.\d{2})/i);
if (match) details.grossAmount = parseFloat(match[1].replace(/,/g, ''));
match = text.match(/Integrated GST 5%\s+([\d,]+\.\d{2})/i);
if (match) details.igst = parseFloat(match[1].replace(/,/g, ''));
match = text.match(/GST Comp Cess\s+([\d,]+\.\d{2})/i);
if (match) details.cess = parseFloat(match[1].replace(/,/g, ''));
match = text.match(/TCS 1%\s+([\d,]+\.\d{2})/i);
if (match) details.tcs = parseFloat(match[1].replace(/,/g, ''));
match = text.match(/(INR .*? Paisa Only)/i);
if (match) details.amountInWords = match[1];
match = text.match(/IRN NO\.:(\S+)/i);
if (match) details.irnNo = match[1];
return details;
}
--
You received this message because you are subscribed to the Google Groups "Google Apps Script Community" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-apps-script-c...@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/google-apps-script-community/201d53fb-fc13-4062-bf67-2d965dd2292dn%40googlegroups.com.