> ## Content Index
> Fetch the complete content index at: https://www.hubwiz.com/blog/llms.txt
> Use this file to discover other available public pages before exploring further.

# 用Gemini自动提取PDF数据
- URL: https://www.hubwiz.com/blog/automate-pdf-data-extraction-using-gemini/
- Published: 2024-12-12T01:14:54.000Z
- Updated: 2024-12-12T01:14:54.000Z
- Description: 在此博客中，我们将使用 Gemini 1.5 Flash 模型和 Google Apps Script 自动执行从 PDF 中提取详细信息并填充 Google Sheet 的过程。
- Author: admin
- Tags: APPLICATION, DOCUMENT EXTRACTION, GEMINI, PDF, GOOGLE SHEET, #Import 2026-10-14 14:41

中小型企业会收到来自供应商的 PDF 发票，需要存储发票号、发票日期、总金额和供应商名称等详细信息。为所有供应商手动执行此操作是一个繁琐且耗时的过程。

在此博客中，我们将使用 Gemini 1.5 Flash 模型和 Google Apps Script 自动执行从 PDF 中提取详细信息并填充 Google Sheet 的过程。

那么让我们开始吧。

> 这个自动​​化功能可以做什么？

此功能旨在自动执行 Google Sheet 内部的手动数据输入过程。此功能使用 Gemini 1.5 Flash 模型从 Google Sheet 中提取所需/指定的详细信息并填充 Google Sheet。

现在我们已经了解了问题和可能的解决方案，让我们开始编码吧。

> 示例 Google Sheet

![](https://www.hubwiz.com/blog/content/images/2024/12/image-501.png)

我将在本博客中使用的 Google Sheet 包含以下详细信息：发票编号、日期、供应商名称、项目说明、税、总金额、到期日、备注、上次更新。

如果你想使用此工作表，请单击[此处](https://docs.google.com/spreadsheets/d/19L5YqNDcfHjoSdilq45n7xOU22NnlgWrrxTkSlkqi7c/copy?ref=hubwiz.com)。

## 1、编写自动化脚本

当你在 Google Sheet 中时，让我们打开脚本编辑器来编写一些 Google Apps 脚本。要打开脚本编辑器，请按照以下步骤操作：

a) 单击扩展并打开脚本编辑器。

![](https://www.hubwiz.com/blog/content/images/2024/12/image-496.png)

b) 这将打开脚本编辑器，如下所示：

![](https://www.hubwiz.com/blog/content/images/2024/12/image-495.png)

我们已经到达脚本编辑器，让我们编写代码 `geminiextract.js`：

```
function processPdfToSheet() {
var archiveFolderId = "YOUR_ARCHIVE_FOLDER_ID";
  const folderId1 = "YOUR_FOLDER_ID";
  var folder = DriveApp.getFolderById(folderId1);
  var files = folder.getFiles(); // Corrected method

  while (files.hasNext()) {
    var file = files.next();
    if (file.getMimeType() === MimeType.PDF) { // Filter PDF files
      var fileId = file.getId();
      var pdfContent = convertPdfToGoogleDoc(fileId, folder);
      var responseData = sendToGemini(pdfContent);
      var details = extractFields(responseData);

      // Update Google Sheet with extracted details
      updateSheet(details);

      // Move the original PDF and the converted Google Doc to the archive folder
      var archiveFolder = DriveApp.getFolderById(archiveFolderId);
      moveFileToArchive(file, archiveFolder);
    }
  }
}

function convertPdfToGoogleDoc(fileId, folder) {
  var file = DriveApp.getFileById(fileId);
  var blob = file.getBlob();
  var newFileName = file.getName().replace(/\.pdf$/, '') + ' converted';
  var resource = {
    title: newFileName,
    mimeType: MimeType.GOOGLE_DOCS
  };
  var options = {
    ocr: true,
    ocrLanguage: 'en'
  };
  var convertedFile = Drive.Files.create(resource, blob, options);
  var doc = DocumentApp.openById(convertedFile.id);
  var pdfContent = doc.getBody().getText();
  var convertedFileObj = DriveApp.getFileById(convertedFile.id);
  convertedFileObj.setTrashed(true); // Move to trash
  return pdfContent;
}

function sendToGemini(pdfData) {
  const GEMINI_KEY = 'YOUR_API_KEY';
  const GEMINI_ENDPOINT = `https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash-latest:generateContent?key=${GEMINI_KEY}`;
  var headers = {
    "Content-Type": "application/json",
    "Accept": "application/json"
  };
  var requestBody = {
    "contents": [
      {
        "parts": [
          {
            "text": `extract the following details: Vendor Name: Invoice Number: Amount Due: Due Date: Description Tax: \n${pdfData}`
          }
        ]
      }
    ]
  };
  var options = {
    "method": "POST",
    "headers": headers,
    "payload": JSON.stringify(requestBody)
  };
  try {
    var response = UrlFetchApp.fetch(GEMINI_ENDPOINT, options);
    var datanew = JSON.parse(response.getContentText());
    return datanew;
  } catch (error) {
    Logger.log('Error calling Gemini API: ' + error);
    return null;
  }
}

function extractFields(datanew) {
  if (!datanew || !datanew.candidates || !datanew.candidates.length) {
    Logger.log('No valid data returned from Gemini.');
    return {};
  }
  
  var textContent = datanew.candidates[0].content.parts[0].text;
  textContent = textContent.replace(/- /g, '').trim();
  var lines = textContent.split('\n');

  var details = {};
  lines.forEach(function (line) {
    var parts = line.split(':');
    if (parts.length === 2) {
      var key = parts[0].replace(/\*\*/g, '').trim();
      var value = parts[1].replace(/\*\*/g, '').trim();
      details[key] = value;
    }
  });

  return details;
}

function updateSheet(details) {
  var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Invoices");
  var range = sheet.getDataRange();
  var values = range.getValues();

  var vendorName = details['Vendor Name'];
  var nameFound = false;

  var currentDate = Utilities.formatDate(new Date(), Session.getScriptTimeZone(), 'MM/dd/yy');
  var formattedDateTime = Utilities.formatDate(new Date(), Session.getScriptTimeZone(), "yyyy-MM-dd HH:mm:ss");

  for (var i = 1; i < values.length; i++) {
    if (values[i][2].toLowerCase() === vendorName.toLowerCase()) { // Compare by Vendor Name
      nameFound = true;
      sheet.getRange(i + 1, 1).setValue(details['Invoice Number']); // Column A
      sheet.getRange(i + 1, 6).setValue(details['Amount Due']); // Column F
      sheet.getRange(i + 1, 7).setValue(details['Due Date']); // Column G
      sheet.getRange(i + 1, 9).setValue("Last updated at: " + formattedDateTime); // Column I
      Logger.log("Updated Row " + (i + 1));
      break;
    }
  }

  if (!nameFound) {
    Logger.log("Vendor not found: " + vendorName);
    var newRow = values.length + 1;

    sheet.getRange(newRow, 1).setValue(details['Invoice Number']); // Column A
    sheet.getRange(newRow, 3).setValue(vendorName); // Column C
    sheet.getRange(newRow, 4).setValue(details['Description']); // Column D
    sheet.getRange(newRow, 5).setValue(vendorName); // Column E
    sheet.getRange(newRow, 6).setValue(details['Amount Due']); // Column F
    sheet.getRange(newRow, 7).setValue(details['Due Date']); // Column G
    sheet.getRange(i + 1, 9).setValue("Last updated at: " + formattedDateTime); // Column I
    Logger.log("New Row Added");
  }
}

function moveFileToArchive(file, archiveFolder) {
  file.moveTo(archiveFolder);
}
```

`processPdfToSheet()` 是启动从 PDF 中提取数据并更新电子表格的过程的主要函数。

我们首先声明两个文件夹 ID。 `archiveFolderId()` 存储已处理的 PDF 和转换后的 Google Docs 存档的文件夹的 ID。 `folderId1()` 存储包含需要处理的 PDF 的文件夹的 ID。

获得文件夹 ID 后，我们使用 `getFolderByID()` 函数来获取文件夹。访问文件夹时，我们会遍历文件夹中的所有文件。对于每个文件，它会检查该文件是否为 PDF。

如果是，它会将 PDF 转换为 Google Doc，提取文本内容，使用 Gemini AI 模型进行处理，从模型的响应中提取相关详细信息，使用这些详细信息更新电子表格，最后将原始 PDF 和转换后的 Google Doc 移动到存档文件夹。

`convertPdfToGoogleDoc()` 函数通过检索 PDF 文件的内容、使用提取的文本创建新的 Google Doc，然后删除转换后的 Google Doc 以避免混乱来处理 PDF 文件。我们使用 Drive API 和 DocumentApp 执行这些操作，确保准确提取文本。

然后，我们返回提取的文本内容，可以进一步处理或在应用程序中使用

然后我们使用 `sendToGemini()` 函数与 Gemini 1.5 Flash 交互，以处理并从文本内容中提取数据。我们构造一个包含提示的请求，该提示指定了我们想要从内容中提取的详细信息，然后将请求发送到 Gemini 1.5 Flash。

如果出现错误，它会记录一条错误消息并返回 null 。如果成功，它会返回我们从 Gemini 1.5 Flash 收到的提取的详细信息。

我们使用 `extractFields()` 函数处理 Gemini 1.5 Flash 的响应以提取相关详细信息。我们检查响应的有效性，提取文本内容，将其拆分成行并遍历每一行以识别键值对。

这些提取的详细信息（例如供应商名称、发票编号等）将以结构化对象的形式返回以供进一步使用。

`updateSheet()` 函数负责管理 Google Sheet 中的条目。它首先检查客户或供应商是否已存在于工作表中。如果找到匹配的条目，该函数将使用新详细信息更新现有记录。但是，如果未找到现有记录，则会创建一个新条目来存储信息。

`moveFileToArchive()` 函数是一个简单的帮助函数，在数据提取和 Google Sheet 更新完成后，它会获取文件并将其移动到存档文件夹。

我们的代码已完成，可以开始使用了。

## 2、检查输出

现在是时候查看代码是否能够访问发票、提取详细信息并成功更新 Google Sheet 了。

![](https://www.hubwiz.com/blog/content/images/2024/12/image-497.png)

你可以直接从编辑器运行代码，也可以使用自定义菜单。运行代码时，你应该在执行日志中获得类似这样的输出。

![](https://www.hubwiz.com/blog/content/images/2024/12/image-500.png)

在这里您可以看到，成功执行后，它可以识别出没有名为 Stellar 的供应商，并为其创建了一个新行。你也可以在 Google Sheet 中查看结果。

![](https://www.hubwiz.com/blog/content/images/2024/12/image-499.png)

它在 Google Sheet 中为新供应商详细信息创建了一个新行。这就是我们使用 Gemini 1.5 Flash 模型和 Google Apps Script 自动化数据提取过程的方式。

## 3、结束语

总之，使用 Google Apps Script 可以自动化从 PDF 甚至文档中输入数据的过程。该功能对于希望加快数据输入过程的小型企业很有帮助。这种方法不仅节省时间，而且还增强了你的整体系统和流程。

本教程的代码可以从这里下载。

---

原文链接：[Automate PDF Data Extraction using Gemini 1.5 Flash and Google Apps Script](https://medium.com/google-cloud/automate-pdf-data-extraction-using-gemini-1-5-flash-and-google-apps-script-48b10a6d722f?ref=hubwiz.com)

汇智网翻译整理，转载请标明出处