原本是請學校教學組利用 AutoCrat 的外掛程式來合併列印學習扶助通知單的,
但教學組發現步驟好像有點多,詢問是否可以再簡化合併列印步驟!
想不到有了之前設計合併列印代課老師簽到單的經驗後,
想說把開學前教學組要發的學習扶助調查通知單也一併請 Gemini 設計
想說把開學前教學組要發的學習扶助調查通知單也一併請 Gemini 設計
Gemini 果然沒讓人失望,趕快來看看如何使用吧!
🎯 程式使用方法:
需準備一個 Google試算表:Google試算表ID
👉👉 Google 試算表範本下載 👈👈
🎯比較要注意的地方就是這邊要跟試算表的欄位順序一致!
// --- 定義 placeholder 陣列 ---
var placeholders = ['{{姓名}}','{{年}}', '{{班}}', '{{座號}}', '{{班別}}', '{{時間}}']; // 依照試算表欄位順序設定
二個 Google文件 檔案:Google文件範本ID、套印目標Google文件ID
(🎯 通知單範本檔案、🎯 請自行設定好一個設定好邊界的空白套印目標檔案)
// --- 設定全域變數 ---
var spreadsheetId = '試算表ID';
var templateDocumentId = '範本文件ID';
var targetDocumentId = '目標文件ID';
function onOpen() {
var ui = SpreadsheetApp.getUi();
ui.createMenu('🚀自訂選單')
.addItem('📄開啟範本文件', 'openTemplateDocumentLink')
.addSeparator()
.addItem('🎯合併所有資料', 'mergeDataToPages')
.addItem('🗑️刪除文件內容', 'clearTargetDocument')
.addToUi();
}
function mergeDataToPages() {
// --- 讀取試算表所有資料 ---
var ss = SpreadsheetApp.openById(spreadsheetId);
var sheet = ss.getSheetByName('工作表1');
var data = sheet.getRange('A2:Z' + sheet.getLastRow()).getValues(); // 讀取 A 到 Z 欄位
var placeholders = sheet.getRange('A1:Z1').getValues()[0]; // 讀取第一列作為 placeholders
// --- 錯誤處理:檢查檔案是否存在 ---
try {
SpreadsheetApp.openById(spreadsheetId);
DriveApp.getFileById(templateDocumentId);
DocumentApp.openById(targetDocumentId);
} catch (e) {
SpreadsheetApp.getActiveSpreadsheet().toast('檔案不存在,請確認 ID 是否正確', '錯誤');
return;
}
// --- 取得目標文件 ---
var targetDoc = DocumentApp.openById(targetDocumentId);
var targetBody = targetDoc.getBody();
// --- 取得 Google 文件範本檔案 ---
var templateFile = DriveApp.getFileById(templateDocumentId);
var templateDoc = DocumentApp.openById(templateFile.getId());
var templateBody = templateDoc.getBody();
// --- 移除範本文件最上方的空白段落 ---
var firstElement = templateBody.getChild(0);
if (firstElement.getType() === DocumentApp.ElementType.PARAGRAPH && firstElement.getText().trim() === "") {
templateBody.removeChild(firstElement);
}
// --- 顯示合併中視窗 ---
var htmlOutput = HtmlService.createHtmlOutput('<p>資料合併中,請稍候...</p>');
var ui = SpreadsheetApp.getUi();
var dialog = ui.showModelessDialog(htmlOutput, '合併中');
// --- 顯示合併進度 ---
SpreadsheetApp.getActiveSpreadsheet().toast('開始合併...', '合併進度');
// --- 定義 placeholder 陣列 ---
var placeholders = ['{{姓名}}','{{年}}', '{{班}}', '{{座號}}', '{{班別}}', '{{時間}}']; // 依照試算表欄位順序設定
// --- 批次處理資料 ---
var batchSize = 10; // 設定每個批次處理的資料筆數
for (var i = 0; i < data.length; i += batchSize) {
var dataBatch = data.slice(i, i + batchSize); // 取得目前的資料批次
// --- 處理目前的資料批次 ---
for (var j = 0; j < dataBatch.length; j++) {
// --- 複製範本內容到目標文件 ---
var templateElements = templateBody.getNumChildren();
for (var k = 0; k < templateElements; k++) {
var element = templateBody.getChild(k).copy();
// --- 立即將資料複製到目標文件 ---
if (element.getType() === DocumentApp.ElementType.TABLE) {
var table = element;
for (var r = 0; r < table.getNumRows(); r++) {
for (var c = 0; c < table.getRow(r).getNumCells(); c++) {
var cell = table.getRow(r).getCell(c);
for (var l = 0; l < placeholders.length; l++) {
cell.replaceText(placeholders[l], dataBatch[j][l]);
}
}
}
targetBody.appendTable(table);
} else if (element.getType() === DocumentApp.ElementType.PARAGRAPH) {
var paragraph = element;
for (var l = 0; l < placeholders.length; l++) {
paragraph.replaceText(placeholders[l], dataBatch[j][l]);
}
targetBody.appendParagraph(paragraph);
} else if (element.getType() === DocumentApp.ElementType.LIST_ITEM) {
var listItem = element;
for (var l = 0; l < placeholders.length; l++) {
listItem.replaceText(placeholders[l], dataBatch[j][l]);
}
targetBody.appendListItem(listItem);
} else {
Logger.log('未處理的元素類型:' + element.getType());
}
}
// --- 在每個資料列的最後一筆資料處理完畢後插入分頁符號 ---
if (j < dataBatch.length - 1) {
targetBody.appendPageBreak();
}
}
// --- 更新合併進度 ---
SpreadsheetApp.getActiveSpreadsheet().toast('已合併 ' + (i + dataBatch.length) + '/' + data.length, '合併進度');
}
// --- 移除所有空白頁 ---
var numChildren = targetBody.getNumChildren();
for (var i = numChildren - 1; i >= 0; i--) {
var child = targetBody.getChild(i);
if (child.getType() === DocumentApp.ElementType.PAGE_BREAK) {
var nextChild = targetBody.getChild(i - 1);
if (nextChild && nextChild.getType() === DocumentApp.ElementType.PAGE_BREAK) {
targetBody.removeChild(child);
}
}
}
// --- 合併完成訊息 ---
SpreadsheetApp.getActiveSpreadsheet().toast('合併完成!', '合併進度');
// --- 關閉「合併中」視窗 ---
ui.alert('合併完成');
// --- 開啟目標檔案的連結 ---
var targetFileLink = `https://docs.google.com/document/d/${targetDocumentId}/edit`;
// --- 建立 HTML 輸出並開啟目標檔案視窗 ---
var htmlOutput = HtmlService.createHtmlOutput(`
<script>
window.open('${targetFileLink}', '_blank');
google.script.host.close();
</script>
`);
// --- 顯示開啟目標檔案的對話方塊 ---
ui.showModalDialog(htmlOutput, '開啟目標檔案');
}
function openTemplateDocumentLink() {
var templateFileLink = `https://docs.google.com/document/d/${templateDocumentId}/edit`;
var htmlOutput = HtmlService.createHtmlOutput(`
<script>
window.open('${templateFileLink}', '_blank');
google.script.host.close();
</script>
`);
SpreadsheetApp.getUi().showModalDialog(htmlOutput, '開啟範本檔案');
}
function clearTargetDocument() {
// --- 錯誤處理:檢查檔案是否存在 ---
try {
DocumentApp.openById(targetDocumentId); // 修正此行
} catch (e) {
SpreadsheetApp.getActiveSpreadsheet().toast('檔案不存在,請確認 ID 是否正確', '錯誤');
return;
}
var targetDoc = DocumentApp.openById(targetDocumentId);
var targetBody = targetDoc.getBody();
targetBody.clear();
SpreadsheetApp.getActiveSpreadsheet().toast('目標文件已清空!', '完成');
Browser.msgBox('目標文件已清空!');
}
快來試試吧~~
沒有留言:
張貼留言
歡迎大家一起留言討論!