Skip to content

Instantly share code, notes, and snippets.

@baku89
Last active August 2, 2024 09:45
Show Gist options
  • Save baku89/5a53ad6d41737c1371f947e9536c35d1 to your computer and use it in GitHub Desktop.
Save baku89/5a53ad6d41737c1371f947e9536c35d1 to your computer and use it in GitHub Desktop.
const sheetInfo = new Map([
['見積書', { range: 'A1:I38' }],
['選定理由書', { range: 'A1:H40' }],
['発注書', { range: 'A1:I38' }],
['注文請書', { range: 'A1:I38' }],
['出張予定表', { range: 'A1:H51' }],
['旅費計算書', { range: 'A1:L23' }],
['納品書', { range: 'A1:I39' }],
['検収書', { range: 'A1:I38' }],
['検収書', { range: 'A1:I38' }],
['出張報告書', { range: 'A1:H51' }],
['請求書', { range: 'A1:I38' }],
['領収書', { range: 'A1:I38' }],
])
function exportPDFs() {
const doc = SpreadsheetApp.getActiveSpreadsheet()
const descriptorSheet = doc.getSheetByName('採択者情報')
const documentListSheet = doc.getSheetByName('証憑書類整理一覧表')
// Retrieve the selected rows
const rows = selectedRows(documentListSheet)
// Collect the PDF information to export
const pdfInfos = rows
.flatMap((row) => {
// B行: 通番
const index = documentListSheet.getRange(row, 2).getValue()
// F行: 費用種別
const kind = documentListSheet.getRange(row, 6).getValue()
// F行: 費用No.
const kindNo = documentListSheet.getRange(row, 7).getValue()
// I行: 内訳枝番
const branch = documentListSheet.getRange(row, 9).getValue()
//AD行: 必要書類リストを元に、PDFの枚数だけ情報を生成
return documentListSheet
.getRange(row, 30)
.getValue()
.split(',')
.map((name) => name.trim())
.filter((name) => sheetInfo.has(name))
.map((sheetName) => {
const { range } = sheetInfo.get(sheetName)
const filename = `${kind}_${branch}_${sheetName}.pdf`
const month = parseInt(index.split('-')[0])
const year = month >= 6 ? 2024 : 2025
const monthFolder = `${year}年${month}月`
const kindFolder = kindNo.toString().padStart(2, '0') + '_' + kind
return {
index,
sheetName,
range,
filename,
monthFolder,
kindFolder,
}
})
})
.flat()
// Retrieve the folder instance by the id
const folderId = descriptorSheet.getRange('B9').getValue()
const folder = DriveApp.getFolderById(folderId)
// Generate the PDF blobs
pdfInfos.forEach((info, i) => {
const path = `${info.monthFolder}/${info.kindFolder}/${info.filename}`
Logger.log(`Exporting ${path}... (${i + 1} / ${pdfInfos.length})`)
const pdf = getPdfBlob(info.index, info.sheetName, info.range)
pdf.setName(info.filename)
// Create a directory if it does not exist
const monthFolder = getOrCreateFolder(folder, info.monthFolder)
const kindFolder = getOrCreateFolder(monthFolder, info.kindFolder)
// Delete the existing file
const files = kindFolder.getFilesByName(info.filename)
while (files.hasNext()) {
files.next().setTrashed(true)
}
kindFolder.createFile(pdf)
})
// const zipBlob = Utilities.zip(pdfBlobs, 'all.zip')
// const downloadURL = DriveApp.createFile(zipBlob).getDownloadUrl()
// const htmlOutput = HtmlService.createHtmlOutput(`
// <html><body>
// <a href="${downloadURL}" target="_blank">Download All ZIP</a>
// </body></html>
// `)
// const ui = SpreadsheetApp.getUi()
// ui.showModalDialog(htmlOutput, 'Download ZIP')
function getOrCreateFolder(parent, name) {
var folders = parent.getFoldersByName(name)
if (folders.hasNext()) {
return folders.next()
} else {
return parent.createFolder(name)
}
}
function selectedRows(sheet) {
const range = sheet.getActiveRange()
// 行番号のリストを取得
const startRow = range.getRow()
const numRows = range.getNumRows()
const rows = []
for (let i = 0; i < numRows; i++) {
rows.push(startRow + i)
}
return rows
}
function encodeQueryParams(params) {
return Object.keys(params)
.map(function (key) {
return encodeURIComponent(key) + '=' + encodeURIComponent(params[key])
})
.join('&')
}
function getPdfBlob(index, sheetName, rangeNotation) {
// 通番をセット
descriptorSheet.getRange('B1').setValue(index)
SpreadsheetApp.flush()
const sheet = doc.getSheetByName(sheetName)
const range = sheet.getRange(rangeNotation)
const url = `https://docs.google.com/spreadsheets/d/${doc.getId()}/export?`
const queryString = encodeQueryParams({
exportFormat: 'pdf',
format: 'pdf',
size: 'A4',
portrait: true,
fith: true,
top_margin: '0.50',
bottom_margin: '0.50',
left_margin: '0.50',
right_margin: '0.50',
sheetnames: false,
printtitle: false,
pagenumbers: false,
gridlines: false,
fzr: false,
gid: sheet.getSheetId(),
range: range.getA1Notation(),
})
const token = ScriptApp.getOAuthToken()
const response = UrlFetchApp.fetch(url + queryString, {
headers: {
Authorization: 'Bearer ' + token,
},
})
const pdfBlob = response.getBlob()
// Wait for a while to avoid the error "Exception: Service invoked too many times for one day: urlfetch."
Utilities.sleep(6000)
return pdfBlob
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment