橫幅按鈕

2024年10月31日 星期四

[Google Apps Script] 自製標籤紙、通知單合併列印

 


想要在 Google 文件運用標籤套印好像沒那麼方便,
因為好像找不到類似 Fill Next 函數來完成下一筆資料的套印;
所以一直都卡在只會套印單張獎狀或通知單!
不過在 Gemini 的協助下終於完成心目中合併列印的想法!
雖然還需要手動調整標籤紙的版面,不過對我來說已經非常夠用了!
趕快來看看如何運作吧!!



這次的想法是要讓使用者感覺可以自行設定合併的內容,
Gemini 幫忙設計了二個檔案來完成我提出的需求。

🎯使用步驟大致如下:
1、事先準備設定好標籤紙大小規格樣式的工作表
2、輸入想要的模版樣式
3、將資料合併到樣版中
4、標籤紙:直接在 #試算表 中列印(因為需要符合標籤紙的規格)
5、通知單:因為只要列印,沒有紙張規格的問題,所以可以運用 #Google文件 連結試算表的功能,到更新連結後一次列印。

步驟一、標籤紙的規格為何?以這邊為例,想要 8張 4*2 這個規格 10.5*7.4 公分;所以請先 單位換算 再新增一個名為 4*2 的工作表,再將儲存格大小設定為 397*280 像素





這邊要提醒 A、D、E 欄大小要設定 21像素,這樣可以很容易微調 標籤的邊界!






可新增文字內容,標籤位置也可隨意移動,
但記得不要不小心把 {{name1}} 標籤給刪除了!


合併資料後記得可以再次修改文字的大小和對齊方式




🎯 列印標籤注意事項:
1、列印:所選的儲存格
2、邊界:自訂數字(標籤紙一般都設為 0)
3、格式設定:取消顯示格線


如果不需要列印標籤紙,只是需要合併資料不需要符號標籤紙規格,
可以將試算表表格複製連結到 Googel 文件 中,
這樣就可以達到一次列印所有合併資料的功能了!


連結試算表的表格後,資料有變更只要點選更新,就可以直接列印通知單了




<!DOCTYPE htm
<html>
  <head>
    <base target="_top">
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/css/bootstrap.min.css">
    <style>
      body {
        width: 90vw;
        height: 90vh;
        /* display: flex;
        justify-content: center;
        align-items: center;          */
      .container {
        position: fixed;
        top: 0;
        left: 50%;
        transform: translateX(-50%);
      }
      }
      /*  讓右側欄位區塊靠右對齊 */
      .right-column {
        text-align: left;
      }
    </style>
  </head>
  <body>
    <div class="container">
      <div class="row">
        <div class="col-md-6">
          <div class="form-group">
            <label for="template">輸入套印文字範本:</label>
            <textarea id="template" class="form-control" rows="10" cols="50">
{{name1}}
{{name2}}
{{name3}}
{{name4}}
{{name5}}</textarea>
          </div>
        </div>
        <div class="col-md-6 right-column">  
          <div>
            <div class="form-group">
              <label for="sheetName">選擇工作表:</label>
              <select id="sheetName" class="form-control">
              </select>
            </div>

            <div class="form-group">
              <label for="labelsPerPage">每頁標籤數量:</label>
              <input type="number" id="labelsPerPage" class="form-control" value="20">
            </div>

            <div class="form-group">
              <label for="labelsPerColumn">每欄標籤數量:</label>
              <input type="number" id="labelsPerColumn" class="form-control" value="10">
            </div>

            <button onclick="submitTemplate()" class="btn btn-primary">建立標籤</button>
          </div>
        </div>
      </div>
    </div>

    <script>
      // 載入工作表名稱
      function loadSheetNames() {
        google.script.run.withSuccessHandler(populateSheetNames).getSheetNames();
      }

      // 將工作表名稱加入到下拉式選單
      function populateSheetNames(sheetNames) {
        var sheetNameSelect = document.getElementById("sheetName");
        // 從索引 1 (第三個工作表) 開始迭代
        for (var i = 2; i < sheetNames.length; i++) {
          var sheetName = sheetNames[i];
          var option = document.createElement("option");
          option.text = sheetName;
          option.value = sheetName;
          sheetNameSelect.add(option);
        }
      }

      // 呼叫載入工作表名稱函式
      loadSheetNames();

      function submitTemplate() {
        var template = document.getElementById("template").value;
        var sheetName = document.getElementById("sheetName").value;
        var labelsPerPage = document.getElementById("labelsPerPage").value; // 取得每頁標籤數量
        var labelsPerColumn = document.getElementById("labelsPerColumn").value; // 取得每欄標籤數量
        google.script.run.createLabels(template, sheetName, labelsPerPage, labelsPerColumn);
        google.script.host.close();
      }
    </script>

    <script src="https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.slim.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/js/bootstrap.min.js"></script>
  </body>
</html>

如果需要一次列印所有通知單這邊請提供 Google 文件ID


function onOpen() {
  // 建立選單
  var ui = SpreadsheetApp.getUi();
  ui.createMenu('🖨️標籤套印')
    .addItem('📑合併文件', 'showTemplateDialog')
    .addItem('🗑️刪除資料', 'clearLabelsSheet')
    .addItem('🎯開啟文件', 'openDocument') // 新增選單項目
    .addToUi();
}

function openDocument() {
  // 文件 ID
  var documentId = '通知單文件ID';

  // 建立 HTML 對話方塊
  var html = HtmlService.createHtmlOutput(`
    <a href="https://docs.google.com/document/d/${documentId}/edit" target="_blank" onclick="google.script.host.close()">👉開啟文件</a>
  `);

  // 顯示對話方塊
  SpreadsheetApp.getUi().showModalDialog(html, '開啟文件');
}


function onEdit(e) {
  // 取得編輯的儲存格
  var cell = e.range;

  // 取得工作表名稱
  var sheetName = cell.getSheet().getName();

  // 檢查是否為「單位換算」工作表的 A 欄
  if (sheetName === '單位換算' && cell.getColumn() === 2) {
    // 取得 A 欄儲存格的值 (公分)
    var cm = cell.getValue();

    // 設定 DPI 值 (可根據需求修改)
    var dpi = 96;

    // 計算像素值
    var pixels = cm * (dpi / 2.54);

    // 將像素值寫入同一列的 B 欄儲存格
    cell.offset(0, 1).setValue(pixels);
  }
}

function showTemplateDialog() {
  // 建立 HTML 對話方塊
  var html = HtmlService.createHtmlOutputFromFile('templateDialog')
    .setWidth(800)
    .setHeight(350);
  SpreadsheetApp.getUi().showModalDialog(html, '輸入套印文字');
}

function getSheetNames() {
  // 取得目前試算表
  var ss = SpreadsheetApp.getActiveSpreadsheet();
 
  // 取得所有工作表名稱
  var sheets = ss.getSheets();
  var sheetNames = [];
  for (var i = 0; i < sheets.length; i++) {
    sheetNames.push(sheets[i].getName());
  }

  return sheetNames;
}

function createLabels(template, sheetName, labelsPerPage, labelsPerColumn) { // 新增參數
  // 取得目前試算表
  var ss = SpreadsheetApp.getActiveSpreadsheet();

  // 取得或建立新的工作表
  var newSheet = ss.getSheetByName(sheetName);
  if (newSheet == null) {
    newSheet = ss.insertSheet(sheetName);
  }

  // --- 參數設定 (可依需求修改) ---
  var labelStartRow = 1; // 標籤起始列
  var labelStartCol = 2; // 標籤起始欄
  // -----------------------------

  // --- 迴圈處理地址資料 ---
  var currentRow = labelStartRow;
  var currentCol = labelStartCol;
  var labelCount = 0; // 目前已印出的標籤數量

  // 取得地址資料
  var sheet = ss.getActiveSheet(); // 資料來源工作表
  var data = sheet.getDataRange().getValues();

  // 遍歷所有資料
  for (var i = 1; i < data.length; i++) {
    // 取得 A 到 E 欄的資料
    var name1 = data[i][0]; // A 欄
    var name2 = data[i][1]; // B 欄
    var name3 = data[i][2]; // C 欄
    var name4 = data[i][3]; // D 欄
    var name5 = data[i][4]; // E 欄

    // 使用範本字串取代變數
    var address = template.replace("{{name1}}", name1)
      .replace("{{name2}}", name2)
      .replace("{{name3}}", name3)
      .replace("{{name4}}", name4)
      .replace("{{name5}}", name5);

    // 填入地址資料
    var cell = newSheet.getRange(currentRow, currentCol);
    cell.setValue(address);

    // 更新列和欄位置
    labelCount += 1; // 標籤數量加 1
    currentRow += 1;

    // 檢查是否需要換欄
    if (currentRow > labelsPerColumn) {
      currentRow = labelStartRow; // 回到起始列
      currentCol += 1;           // 換到下一資料欄
    }

    // 檢查是否需要換頁
    if (labelCount >= labelsPerPage) {
      currentRow = labelStartRow; // 回到起始列
      currentCol += 2;           // 跳到下一個區塊 (兩個欄位 + 間距)
      labelCount = 0; // 重置標籤數量
    }
  }
}

function clearLabelsSheet() {
  // 取得目前試算表
  var ss = SpreadsheetApp.getActiveSpreadsheet();

  // 取得目前啟用的工作表
  var activeSheet = ss.getActiveSheet();

  // 顯示確認訊息方塊
  var ui = SpreadsheetApp.getUi();
  var response = ui.alert(
    '確認刪除',
    '您確定要清除 ' + activeSheet.getName() + ' 工作表的所有內容嗎?',
    ui.ButtonSet.YES_NO
  );

  // 檢查使用者是否選擇 "是"
  if (response == ui.Button.YES) {
    // 清除工作表內容
    activeSheet.clearContents();
  }
}



快來試試吧~~




沒有留言:

張貼留言

歡迎大家一起留言討論!