upload ไฟล์ผ่าน GoogleSheet ไปยัง GoogleDrive

Code.gs

..................................................................................................................................................................... 


// <<< แก้ตรงนี้: ใส่ Folder ID ของโฟลเดอร์ Google Drive ปลายทาง

const FOLDER_ID = '1OLZib_Pp961usiQR41z-uvPrFy0UZaIo2'; // <<< แก้ตรงนี้


function onOpen() {

  SpreadsheetApp.getUi()

    .createMenu('Attach')

    .addItem('Upload file to cell', 'openUploadSidebar')

    .addToUi();

}


function openUploadSidebar() {

  const html = HtmlService.createHtmlOutputFromFile('Sidebar')

    .setTitle('Upload & Link to Cell');

  SpreadsheetApp.getUi().showSidebar(html);

}


function uploadAndInsert(payload) {

  if (!FOLDER_ID || FOLDER_ID === 'PUT_YOUR_FOLDER_ID_HERE') {

    throw new Error('กรุณาใส่ FOLDER_ID ใน Code.gs ก่อนใช้งาน'); // <<< แจ้งเตือนถ้าไม่ได้แก้

  }


  const folder = DriveApp.getFolderById(FOLDER_ID); // <<< ใช้ FOLDER_ID ที่แก้ไป


  const base64 = payload.dataUrl.split(',')[1];

  const bytes = Utilities.base64Decode(base64);

  const blob = Utilities.newBlob(

    bytes,

    payload.mimeType || 'application/octet-stream',

    payload.name || 'upload.bin'

  );

  const file = folder.createFile(blob);


  file.setSharing(DriveApp.Access.ANYONE_WITH_LINK, DriveApp.Permission.VIEW);


  const url = file.getUrl();

  const sheet = SpreadsheetApp.getActiveSheet();

  const targetRow = payload.row + (payload.offset || 0);

  const targetCol = payload.col;


  let value;

  if (payload.asHyperlink) {

    const text = (payload.displayText && payload.displayText.trim()) || file.getName();

    const safeText = text.replace(/"/g, '""');

    const safeUrl = url.replace(/"/g, '""');

    value = `=HYPERLINK("${safeUrl}","${safeText}")`;

  } else {

    value = url;

  }


  sheet.getRange(targetRow, targetCol).setValue(value);


  return { id: file.getId(), name: file.getName(), url, row: targetRow, col: targetCol };

}


function getActiveCellRC() {

  const range = SpreadsheetApp.getActiveSheet().getActiveCell();

  return { row: range.getRow(), col: range.getColumn() };

}



Sidebar.html 


.................................................................................................................................................................

<!DOCTYPE html>

<html>

  <head>

    <meta charset="utf-8" />

    <style>

      body { font-family: system-ui, Arial, sans-serif; padding: 12px; }

      .box { border: 1px solid #ddd; border-radius: 8px; padding: 12px; }

      .row { margin-bottom: 10px; }

      button { padding: 8px 12px; border: 0; border-radius: 6px; cursor: pointer; }

      .primary { background: #1a73e8; color: #fff; }

      .muted { font-size: 12px; color: #666; }

      .progress { margin-top: 6px; font-size: 12px; }

      input[type="text"] { width: 100%; padding: 6px 8px; box-sizing: border-box; }

    </style>

  </head>

  <body>

    <h2>Upload & Link to Cell</h2>

    <div class="box">

      <div class="row">

        <label><b>Choose file(s)</b></label><br>

        <input id="file" type="file" multiple />

        <div class="muted">Tip: เลือกหลายไฟล์ได้ ระบบจะวางลิงก์เรียงลงตามแถว เริ่มที่เซลล์ที่เลือก</div>

      </div>


      <div class="row">

        <label>

          <input id="asHyperlink" type="checkbox" checked />

          ใส่เป็นลิงก์แบบ HYPERLINK (แสดงข้อความแทน URL)

        </label>

      </div>


      <div class="row">

        <label>Display text (ถ้าเว้นไว้ จะใช้ชื่อไฟล์)</label>

        <input id="displayText" type="text" placeholder="เช่น ใบงานนักเรียน, รูปหน้าปก ฯลฯ" />

      </div>


      <div class="row">

        <button class="primary" id="btnUpload">Upload & Insert</button>

      </div>


      <div id="status" class="progress"></div>

    </div>


    <script>

      const $ = (id) => document.getElementById(id);


      document.getElementById('btnUpload').addEventListener('click', async () => {

        const input = $('file');

        const files = input.files;

        if (!files || files.length === 0) {

          return setStatus('กรุณาเลือกไฟล์ก่อน', true);

        }


        setDisabled(true);

        setStatus('กำลังเตรียมอัปโหลด...');


        // ขอพิกัดเซลล์ที่เลือกจากฝั่งเซิร์ฟเวอร์ไม่ได้โดยตรง

        // ใช้วิธีให้ฝั่งเซิร์ฟเวอร์อ่าน ActiveCell เอง: เราจะส่ง row/col จากฝั่งเซิร์ฟเวอร์ไม่จำเป็น

        // แต่เพื่อความชัดเจน ขอพิกัดจากฝั่งเซิร์ฟเวอร์ด้วยฟังก์ชันเล็ก ๆ ก็ได้

        google.script.run.withSuccessHandler(({row, col}) => {

          uploadSequential(files, row, col);

        }).withFailureHandler(err => {

          setStatus('เกิดข้อผิดพลาด: ' + err.message, true);

          setDisabled(false);

        }).getActiveCellRC();

      });


      function uploadSequential(fileList, startRow, startCol) {

        const asHyperlink = $('asHyperlink').checked;

        const displayText = $('displayText').value || '';


        const files = Array.from(fileList);

        let idx = 0;


        const next = () => {

          if (idx >= files.length) {

            setStatus('อัปโหลดเสร็จทั้งหมดแล้ว ✅');

            setDisabled(false);

            return;

          }

          const f = files[idx];

          setStatus(`อัปโหลด: ${f.name} (${idx+1}/${files.length}) ...`);

          const reader = new FileReader();

          reader.onload = function(e) {

            const dataUrl = e.target.result; // base64 dataURL

            const payload = {

              dataUrl,

              name: f.name,

              mimeType: f.type || 'application/octet-stream',

              asHyperlink,

              displayText,

              row: startRow,

              col: startCol,

              offset: idx // วางลงแถวถัดไปเรื่อย ๆ

            };

            google.script.run

              .withSuccessHandler(res => {

                setStatus(`เสร็จ: ${res.name} → R${res.row}C${res.col}`);

                idx++;

                next();

              })

              .withFailureHandler(err => {

                setStatus('เกิดข้อผิดพลาด: ' + err.message, true);

                setDisabled(false);

              })

              .uploadAndInsert(payload);

          };

          reader.onerror = function() {

            setStatus('อ่านไฟล์ไม่สำเร็จ: ' + f.name, true);

            setDisabled(false);

          };

          reader.readAsDataURL(f);

        };


        next();

      }


      function setDisabled(disabled) {

        $('btnUpload').disabled = disabled;

        $('file').disabled = disabled;

        $('asHyperlink').disabled = disabled;

        $('displayText').disabled = disabled;

      }


      function setStatus(msg, isError) {

        const el = $('status');

        el.textContent = msg;

        el.style.color = isError ? '#c00' : '#333';

      }

    </script>

  </body>

</html>


Latest
Previous
Next Post »