ข้ามไปเนื้อหา
← เครื่องมือทั้งหมด
เอกสารพร้อมใช้

OCR Read - Shopee E-Com

อ่านเอกสาร ใบเสร็จรับเงิน/ใบกำกับภาษี เพื่อจัดทำรายงานสรุปค่าใช้จ่ายประจำเดือน

วิธีตั้งค่า Google และใช้งาน Apps Script

เครื่องมือนี้อ่าน PDF ใบเสร็จ/ใบกำกับภาษีค่าบริการ Shopee ใน Google Drive แล้วบันทึกลิงก์ข้อมูลลง Google Sheets เพื่อจัดทำรายงานสรุปค่าใช้จ่ายค่าบริการและค่าขนส่งในสิ้นเดือน

เตรียมก่อนเริ่ม

  • ใช้บัญชี Google ที่เข้าถึงโฟลเดอร์ต้นทางและแก้ไขชีตปลายทางได้
  • สร้างโฟลเดอร์เฉพาะสำหรับ PDF และชีตใหม่สำหรับทดลอง
  • ดาวน์โหลดไฟล์เอกสารค่าใช้จ่ายจาก Shopee เพื่อนำมาทำรายงานประจำเดือน ref : วิธีการดาวน์โหลดใบกำกับภาษี

1. สร้าง Google Sheets

เปิด Google Sheets แล้วสร้างไฟล์ใหม่สำหรับรายงานค่าบริการ Shopee เริ่มจากไฟล์เปล่าเพื่อทดลองกับ PDF 1–2 ไฟล์ก่อนใช้กับข้อมูลจริง

จุดที่ดูในภาพ: ชื่อ Untitled spreadsheet ด้านซ้ายบน

2. ตั้งชื่อไฟล์และแท็บปลายทาง

ตั้งชื่อไฟล์ตามต้องการ เช่น Report_Shopee E-com แล้วเปลี่ยนชื่อแท็บด้านล่างเป็น M_Shopee ให้ตรงตัวพิมพ์และขีดล่าง จากนั้นเพิ่มหัวตารางในแถว 1 ก่อนรัน เพราะโค้ดเริ่มอ่านรายการเดิมจากแถว 2

จุดที่ดูในภาพ: ชื่อไฟล์ด้านซ้ายบน และแท็บ M_Shopee ด้านล่าง

คอลัมน์หัวตารางแถว 1
Aลิงก์ PDF
Bเลขที่เอกสาร
Cวันที่
Dมูลค่าก่อน VAT
EVAT
Fยอดรวม

ภาพต้นฉบับยังไม่มีหัวตาราง ให้เพิ่มหัวตารางก่อนรันจริง และแยกสูตรหรือข้อมูลอื่นออกจากแท็บนี้

3. เปิด Apps Script

ใน Google Sheets เลือก Extensions → Apps Script หรือ ส่วนขยาย → Apps Script จะเปิดหน้าแก้ไขโค้ด ตั้งชื่อโปรเจกต์ให้จำได้ เช่น Shopee PDF Reader

จุดที่กดในภาพ: เมนู Extensions แล้วเลือก Apps Script

4. คัดลอก Sheet ID

ดู URL ของไฟล์ Google Sheets แล้วคัดลอกเฉพาะข้อความระหว่าง /d/ และ /edit ไม่คัดลอก URL ทั้งเส้น

plain texthttps://docs.google.com/spreadsheets/d/SHEET_ID/edit

จุดที่ดูในภาพ: แถบ URL ด้านบน รหัสตรงกลางคือ Sheet ID

5. สร้างโฟลเดอร์ PDF และคัดลอก Folder ID

เปิด Google Drive สร้างหรือเลือกโฟลเดอร์ที่จะเก็บ PDF ค่าบริการ Shopee แล้วคัดลอกข้อความหลัง /folders/ หากมี ? ให้หยุดก่อนเครื่องหมายนี้ วาง PDF ไว้ในโฟลเดอร์นั้นโดยตรง เพราะโค้ดไม่ค้นโฟลเดอร์ย่อย ถ้าจะใช้โฟลเดอร์ outputs ต้องเปิด outputs แล้วใช้ ID ของโฟลเดอร์นั้น

plain texthttps://drive.google.com/drive/folders/FOLDER_ID

จุดที่ดูในภาพ: แถบ URL และชื่อโฟลเดอร์ที่เปิดอยู่

6. วางโค้ดและใส่ ID ของคุณ

เปิด Code.gs ลบโค้ดตัวอย่าง แล้ววางโค้ดที่แนบในหน้านี้ให้ครบ เปลี่ยนเฉพาะค่าภายในเครื่องหมายอัญประกาศสองบรรทัดต่อไปนี้

javascriptvar folderId = 'FOLDER_ID_ของคุณ';
var sheetId = 'SHEET_ID_ของคุณ';
javascript// ==========================================

// 🛒 1. M_SHOPEE

// ==========================================

function syncPdfToSheet_M_Shopeeonly() {

var folderId = 'Folder ID';

var sheetId = 'Sheet ID';

var folder = DriveApp.getFolderById(folderId);

var files = folder.getFilesByType(MimeType.PDF);

var spreadsheet = SpreadsheetApp.openById(sheetId);

var sheet = spreadsheet.getSheetByName("M_Shopee");

if (!sheet) {

Logger.log("❌ ไม่พบชีตที่ชื่อ 'M_Shopee'");

return;

}

var data = sheet.getDataRange().getValues();

var sheetFileIds = new Map();

for (var i = 1; i < data.length; i++) {

var pdfUrl = data[i][0];

if (pdfUrl && pdfUrl.toString().includes("drive.google.com/file/d/")) {

var fileId = pdfUrl.split("/d/")[1].split("/")[0];

if (sheetFileIds.has(fileId)) {

sheet.deleteRow(i + 1);

i--;

} else {

sheetFileIds.set(fileId, i + 1);

}

}

}

var newFiles = [];

var existingFiles = new Set();

while (files.hasNext()) {

var file = files.next();

var fileId = file.getId();

var pdfUrl = "https://drive.google.com/file/d/" + fileId;

existingFiles.add(fileId);

if (!sheetFileIds.has(fileId)) {

newFiles.push({ id: fileId, url: pdfUrl });

}

}

var rowsToDelete = [];

for (let [fileId, rowIndex] of sheetFileIds) {

if (!existingFiles.has(fileId)) {

rowsToDelete.push(rowIndex);

}

}

rowsToDelete.sort((a, b) => b - a).forEach(row => sheet.deleteRow(row));

function cleanText(text, prefix) {

if (!text) return "";

text = text.replace(prefix, "").trim();

text = text.replace(/\s+/g, "");

text = text.replace(/\u00A0/g, "");

return text;

}

newFiles.forEach(file => {

try {

var docFile = Drive.Files.copy({ mimeType: MimeType.GOOGLE_DOCS }, file.id);

Utilities.sleep(1000);

var docId = docFile.id;

var doc = DocumentApp.openById(docId);

var text = doc.getBody().getText().trim();

DriveApp.getFileById(docId).setTrashed(true);

if (!text) {

sheet.appendRow([file.url, "Error: No Text", "", "", "", ""]);

return;

}

var lines = text.split('\n').map(line => line.trim());

var invoiceNo = "", dateValue = "", amount = "", vat = "", total = "";

for (var i = 0; i < lines.length; i++) {

var line = lines[i];

if (line.includes("เลขที่/ No.")) { invoiceNo = cleanText(line, "เลขที่/ No."); }

else if (line.includes("วันที่/ Date")) { dateValue = cleanText(line, "วันที่/ Date"); }

else if (line.includes("มูลค่าก่อนภาษีมูลค่าเพิ่มหลังส่วนลด/ Total Value of Services (Excluded VAT) after discount")) {

var rawText = cleanText(line, "มูลค่าก่อนภาษีมูลค่าเพิ่มหลังส่วนลด/ Total Value of Services (Excluded VAT) after discount");

if (rawText.includes("ภาษีมูลค่าเพิ่ม")) {

amount = rawText.split("ภาษีมูลค่าเพิ่ม")[0];

if (rawText.includes("VAT7%")) { vat = rawText.split("VAT7%")[1]; }

} else { amount = rawText; }

}

else if (amount === "" && line.includes("มูลค่าก่อนภาษีมูลค่าเพิ่ม/ Total Value of Services (Excluded VAT)")) {

var rawText = cleanText(line, "มูลค่าก่อนภาษีมูลค่าเพิ่ม/ Total Value of Services (Excluded VAT)");

if (rawText.includes("ภาษีมูลค่าเพิ่ม")) {

amount = rawText.split("ภาษีมูลค่าเพิ่ม")[0];

if (rawText.includes("VAT7%")) { vat = rawText.split("VAT7%")[1]; }

} else { amount = rawText; }

}

else if (vat === "" && line.includes("ภาษีมูลค่าเพิ่ม 7%/ VAT 7%")) {

vat = cleanText(line, "ภาษีมูลค่าเพิ่ม 7%/ VAT 7%");

}

else if (line.includes("มูลค่าบริการรวมภาษีมูลค่าเพิ่ม/ Total Value of Services (Included VAT)")) {

total = cleanText(line, "มูลค่าบริการรวมภาษีมูลค่าเพิ่ม/ Total Value of Services (Included VAT)");

}

else if (line.includes("จำนวนเงินรวม/ Total amount")) {

total = cleanText(line, "จำนวนเงินรวม/ Total amount");

}

}

sheet.appendRow([file.url, invoiceNo, dateValue, amount, vat, total]);

} catch (e) {

sheet.appendRow([file.url, 'Conversion Failed: ' + e.message, "", "", "", ""]);

}

});

var lastRow = sheet.getLastRow();

var lastCol = sheet.getLastColumn();

if (lastRow > 1) {

var range = sheet.getRange(2, 1, lastRow - 1, lastCol);

range.sort({column: 3, ascending: true});

}

Logger.log("✅ M_Shopee อัปเดตเสร็จสิ้น!");

}

คงชื่อฟังก์ชัน syncPdfToSheet_M_Shopeeonly() และ getSheetByName("M_Shopee") ให้ตรงกับคู่มือ

จุดที่แก้ในภาพ: บรรทัด var folderId และ var sheetId

7. บันทึกโค้ด

กด Save รูปแผ่นดิสก์ในแถบเครื่องมือ หรือ Ctrl+S / Command+S แล้วรอให้ Unsaved changes หายไป หากช่องฟังก์ชันยังขึ้น No functions ให้ตรวจว่าโค้ดครบ ไม่มีข้อผิดพลาดไวยากรณ์ และบันทึกแล้ว

จุดที่กดในภาพ: ปุ่ม Save รูปแผ่นดิสก์ด้านบน

8. เพิ่มบริการ Drive

ที่แถบซ้ายกดเครื่องหมาย + ข้าง Services เพื่อเปิดหน้าต่าง Add a service ระวังอย่ากด + ข้าง Libraries

จุดที่กดในภาพ: + ทางขวาของคำว่า Services

10. เลือก Drive API และเวอร์ชัน

เลื่อนหา Drive API เลือก Version = v2 และ Identifier = Drive แล้วกด Add ตามภาพ เมื่อเสร็จต้องเห็น Drive ใต้ Services คู่มือนี้ใช้ v2 ตามภาพและโค้ดต้นฉบับ หากจะใช้ v3 ต้องปรับวิธีแปลง PDF และทดสอบแยก

สำหรับโปรเจกต์ Google Cloud แบบ default ที่ Apps Script สร้างให้ การเพิ่มบริการจะเปิด API ให้ด้วย หากเชื่อม standard Cloud project ไว้เอง ให้เปิด Google Drive API ใน Cloud Console ของโปรเจกต์นั้นเพิ่มเติม โค้ดใช้ DriveApp, DocumentApp และ SpreadsheetApp ที่เป็นบริการในตัว จึงไม่ต้องเพิ่ม Docs API หรือ Sheets API สำหรับการเรียกใช้เหล่านี้

จุดที่กดในภาพ: Drive API → Version v2 → Identifier Drive → Add

11. อัปโหลด PDF และรันครั้งแรก

อัปโหลด PDF ตัวอย่าง 1–2 ไฟล์เข้าโฟลเดอร์ที่กำหนดใน folderId โดยตรง กลับ Apps Script กด Save เลือกฟังก์ชัน syncPdfToSheet_M_Shopeeonly แล้วกด Run เมื่อขึ้น Authorization required ให้กด Review permissions และเลือกบัญชี Google ที่เข้าถึงโฟลเดอร์และแก้ไขชีตได้

จุดที่กดในภาพ: Review permissions

12. ตรวจคำเตือนของ Google

หากพบ Google hasn’t verified this app ให้ตรวจว่าเป็นโปรเจกต์ที่คุณสร้างและโค้ดที่คุณตรวจแล้ว หากยังไม่มีลิงก์ไปต่อ ให้กด Advanced แล้วเลือก Go to [ชื่อโปรเจกต์] (unsafe) ภาพนี้เปิด Advanced แล้วจึงเห็นลิงก์ไปต่อ หากองค์กรบล็อกการอนุญาต ให้ติดต่อผู้ดูแล Google Workspace

จุดที่ดูและกดในภาพ: หัวคำเตือน และ Go to Untitled project (unsafe)

13. ตรวจรายการสิทธิ์และยืนยัน

อ่านรายการสิทธิ์ก่อนกด Continue โค้ดต้องอ่านไฟล์ใน Drive สร้าง Google Docs ชั่วคราวแล้วนำไปถังขยะ และเขียนหรือลบแถวใน Sheets หน้าต่างอนุญาตอาจต่างกันตามบัญชีและภาษา ใช้บัญชีที่เข้าถึงทั้งโฟลเดอร์และชีตได้

จุดที่ดูและกดในภาพ: รายการสิทธิ์ Drive / Docs / Sheets และ Continue ด้านล่าง

14. ตรวจผลการรันและข้อมูลในชีต

เมื่ออนุญาตเสร็จ หากสคริปต์ยังไม่เริ่มทำงานให้กด Run อีกครั้ง รอ Execution log แสดง Execution completed แล้วกลับแท็บ M_Shopee ตรวจข้อมูลแถว 2 เป็นต้นไป เปิด PDF ต้นฉบับเทียบเลขที่เอกสาร วันที่ ยอดก่อน VAT VAT และยอดรวม

ภาพนี้ยืนยันเฉพาะการจบการรัน ไม่ได้ยืนยันว่า OCR อ่านข้อมูลครบและถูกต้อง เพราะโค้ดจับข้อผิดพลาดแล้วเขียนเป็นแถว error ได้ด้วย สำหรับครั้งต่อไปให้อัปโหลด PDF ใหม่เข้าโฟลเดอร์เดิมแล้วกด Run สคริปต์จะข้าม File ID ที่อยู่ในคอลัมน์ A แล้ว และไม่มี Trigger อัตโนมัติในโค้ดเดิม

จุดที่ดูในภาพ: Execution log และ Execution completed

ปัญหาที่พบบ่อย

  • ไม่พบชีต M_Shopee: ตรวจชื่อแท็บให้ตรง และ sheetId ชี้ไฟล์ที่ถูกต้อง
  • Drive is not defined: เพิ่ม Drive API ใน Services และตั้ง Identifier เป็น Drive
  • เปิดโฟลเดอร์หรือชีตไม่ได้: ใช้เฉพาะ ID ไม่ใช่ URL ทั้งเส้น และตรวจสิทธิ์ของบัญชีที่อนุญาต
  • รันสำเร็จแต่ไม่มีแถว: ตรวจว่ามี PDF ในโฟลเดอร์โดยตรงและ File ID ยังไม่เคยบันทึก
  • Error: No Text / Conversion Failed: ตรวจคอลัมน์ B ทดลองเปิด PDF ด้วย Google Docs และตรวจการแปลง PDF กับเวอร์ชัน API
  • บางช่องว่างหรือยอดผิด: ตรวจ PDF ต้นฉบับ เพราะ OCR อาจแบ่งบรรทัดไม่ตรงกับข้อความที่โค้ดค้นหา
  • แก้ PDF แล้วข้อมูลไม่เปลี่ยน: โค้ดข้าม File ID ที่มีในชีตแล้ว หากต้องการลองใหม่ให้สำรองชีตก่อน ลบเฉพาะแถว error ของไฟล์นั้น แล้วรันซ้ำ
  • แถวหายหลังย้าย PDF: โค้ดเดิมลบแถวเมื่อไม่พบไฟล์ในโฟลเดอร์ต้นทาง ควรคง PDF ไว้หรือปรับนโยบาย sync ก่อนใช้เป็นทะเบียนถาวร

ทางเลือก: รันอัตโนมัติภายหลัง

หลังแก้ปัญหาลบแถวและทดลองรันด้วยตนเองผ่านแล้ว เปิด Triggers รูปนาฬิกาที่แถบซ้าย → Add Trigger → เลือก syncPdfToSheet_M_Shopeeonly → deployment Head → Event source Time-driven → เลือกช่วงเวลา เช่น ทุก 1 ชั่วโมง → Save บัญชีผู้สร้าง Trigger ต้องเข้าถึงโฟลเดอร์และชีตได้ ส่วนนี้ไม่มีภาพหน้าต่าง Trigger ในภาพต้นฉบับ

บทความดูเครื่องมือ