藝術科技共舞:OCR在文創娛樂業中的奇妙啟發

喜劇之王

本篇文章是要跟一位朋友致敬,薩泰爾娛樂 共同創辦人和氣資本合夥人 Sunny,因為她才有這篇文章,她是一位非IT本科生(台大戲劇系),從事著與資訊業八竿子打不著的工作,文創娛樂業(雖然說未來AI應該會有相關…),但T編看到一位希望透過資訊技術,改善行業內管理與溝通問題的管理者,自己透過ChatGPT一問一答方式,由無到有,做出許多令人驚豔的小應用,用於她的工作與團隊協作上,記得她說過 導入資訊科技,應減少改變使用者習慣,進而減少導入的阻力,也是如此她鞭策著我們致力提供更簡單的應用給使用者.

這次透過Google Sheet結合發票辨識,節省財務會計整理憑證時間,也讓同仁可以快速進行報帳,讓大家可以喝杯茶,好好的看看單口喜劇 (誤

零、先要有個Google帳號

首先您要有一個Google Sheet帳號,通常您有Gmail就可以使用Google Sheet了,沒有請趕緊申請
吧!

貳、開工

登入Google Sheet,然後新建一個試算表

參、調整一下試算表內容

  • 修改試算表名稱
  • 為試算表增加表頭

肆、開始寫程式

不用害怕,很簡單的只要照著這個複製貼上修改一下即可

1. 擴充功能-開啟Apps Script

2.修改專案名稱

3.將範例程式貼上,每個地方有說明下是做什麼用的,請依據自己需求調整,記得修改:

  • ocrApiUrl = “{{輸入發票辨識服務位置}}”; // 實際發票辨識OCR位置
  • username = “{{輸入您自己的帳號}}”; // 實際帳號
  • password = “{{輸入您自己的密碼}}”; // 實際密碼
  • TaxID: ‘{{輸入您自己的統編}}’ //會進行統編檢核
function onOpen() {
  var ui = SpreadsheetApp.getUi();
  ui.createMenu('發票自動OCR')
      .addItem('上傳檔案', 'showUploadDialog')
      .addToUi();
}

function showUploadDialog() {
  var html = `
    <html>
    <body>
      <input type="file" id="fileInput" accept="image/*">
      <br>
      <input type="button" value="Upload" onclick="uploadFile()">
    </body>
    <script>
      function uploadFile() {
        var fileInput = document.getElementById('fileInput');
        var file = fileInput.files[0];
        if (file) {
          var reader = new FileReader();
          reader.readAsDataURL(file);
          reader.onload = function(e) {
            var fileData = e.target.result.split(',')[1];
            google.script.run.withSuccessHandler(function(imageUrl) {
              alert("File uploaded successfully."); // 提醒上傳完成
              google.script.host.close(); // 關閉對話視窗
            }).uploadImageToDrive(fileData, file.name);
          }
        }
      }
    </script>
    </html>
  `;
  var htmlOutput = HtmlService.createHtmlOutput(html).setWidth(300).setHeight(150);
  SpreadsheetApp.getUi().showModalDialog(htmlOutput, 'Upload Image');
}



function uploadImageToDrive(fileData, fileName) {
  // 將圖片上傳至 Google Drive
  var folder = DriveApp.getRootFolder();
  var blob = Utilities.newBlob(Utilities.base64Decode(fileData), 'image/jpeg', fileName);
  var file = folder.createFile(blob);

  // 取得Google Drive圖片位置
  var imageUrl = file.getUrl();
  

  //Logger.log("Image URL: " + imageUrl);


  // 取得圖片實際位置
  var fileId = file.getId();
  var directUrl = "https://drive.google.com/uc?export=view&id=" + fileId;

  // 取得目前點選的單元格
  var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
  var activeCell = sheet.getActiveCell();

  // 將圖片位置寫入目前點選的單元格
  activeCell.setValue(directUrl);
  

  ocrText =performOCR(fileId)
  writeOCRDataToSheet(ocrText)
  
  // 回傳URL與OCR結果
  return { imageUrl: directUrl, ocrText: ocrText };

  
}

function performOCR(fileId) {
  // 從Google Drive取得圖片為 Blob的資料 
  var imageBlob = DriveApp.getFileById(fileId).getBlob();

  // OCR API 请求 URL
  var ocrApiUrl = "{{輸入發票辨識服務位置}}"; // 實際發票辨識OCR位置
  // Basic Auth API基礎認證
  var username = "{{輸入您自己的帳號}}"; // 實際帳號
  var password = "{{輸入您自己的密碼}}"; // 實際密碼

  // 依據OCR API所需要傳送的資料,整理發送到辨識OCR的
  var payload = {
    UpLoadFile: imageBlob,
    TaxID: '{{輸入您自己的統編}}'
  };

  // 透過POST與 Basic Auth發送OCR請求
  var options = {
    method: "post",
    headers: {
      "Authorization": "Basic " + Utilities.base64Encode(username + ":" + password)
    },
    payload: payload
  };


  var response;
  try {
    response = UrlFetchApp.fetch(ocrApiUrl, options);
  } catch (e) {
    console.error("Error:", e);
    if (e.hasOwnProperty("content")) {
      console.error("Response content:", e.content);
    }
  }

    var ocrText = response.getContentText();

    // 回傳辨識結果
    return ocrText;
}

function writeOCRDataToSheet(ocrData) {
  var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
  var activeCell = sheet.getActiveCell();
  var data = JSON.parse(ocrData);

  // 整理資料
  var sysinfo = data["0"]["Sysinfo"];
  var result = data["0"]["Result"];

  // 將表頭與API回傳Key對應
  var headerMapping = {
    "Type": "辨識型態",
    "Version": "版本",
    "Message": "訊息",
    "Date": "日期",
    "ReceiptNum": "統一編號",
    "BuyerNum": "買方統編",
    "SellerNum": "賣方統編",
    "NoTaxCharge": "未稅金額",
    "Charge": "含稅金額",
    "Tax": "稅額",
    "ReceiptFormat": "格式"
  };

  // 寫入資料
  writeDataToSheet(sysinfo, activeCell, headerMapping);
  writeDataToSheet(result, activeCell, headerMapping);
}

function writeDataToSheet(data, startCell, headerMapping) {
  var sheet = startCell.getSheet();
  var row = startCell.getRow();

  for (var key in data) {
    var columnHeader = headerMapping[key];
    if (columnHeader) {
      var columnIndex = sheet.getRange(1, 1, 1, sheet.getLastColumn()).getValues()[0].indexOf(columnHeader) + 1;
      if (columnIndex > 0) {
        sheet.getRange(row, columnIndex).setValue(data[key]);
      }
    }
  }
}

伍、寫好了,進行程式部署吧

這邊要注意的是,因為會存取Google Drive將上傳的圖片存下來,在跟外部交互的時候Google也需要一些權限允許,就先依據圖片說明讓權限通過即可.

依據畫面提醒授予權限

允許googleSheet與googleDrive

部署完成

陸、這樣就好了嗎?

是的!就這麼快速~

接著就可以測試,請回到試算表,重新整理一下,就會跑出一個 ‘發票自動OCR’的按鈕,我們就可以上傳圖片進行OCR辨識摟.

點選後神奇的事情就發生了

上傳發票
上傳發票

自動辨識出結果

有發現到嗎?除了幫你辨識完成,還同步在GoogleDrive儲存喔!

Google Sheet結合發票辨識應用

柒、結論

這只是T編簡單的示範案例,其實可以應用的方面還很多,例如用在Google 文件,或是將這個程式在修改人性化漂亮一點,包含多張上傳,有機會T編在展示給各位看.

捌、致謝

以上致謝Sunny她身兼多職身兼多職,同時也是一位重度的工具使用者與作家(應該要這樣說嗎,有興趣歡迎訂閱她的電子報 無用之用 | Master of None

捌、Coming Soon

最後T編說,可是這樣我需要購買一整套OCR服務嗎?我要自建會不會很麻煩?我不懂程式也不會管理這些怎麼辦?
不用擔心,韜睿軟體即將推出 Swift OCR Protal 智慧辨識API平台,只需要點選您需要的服務,然後像是利用剛剛的Google Sheet或是自身其他系統都可以進行整合,隨選即用免訓練過程,快速上手!

十一、說明

本篇文章之圖片來自Wiki Media 喜劇之王封面,但由於原圖過小故有點跑版也請見諒!

Loading

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *