import fs from 'fs'; //import util from 'util'; import path from 'path'; //コマンド実行モジュール import childProcess from 'child_process'; //const exec = util.promisify(childProcess.exec); //-------------------------------------------------------------------------------------------- //フォルダ名定義 const inputDir = 'pdf'; const outputDir = 'output'; const outputCsvDir = 'outputCsv'; //プリザンター実行変数 const pleasanter = 'https://nextoffice.next-hd.co.jp/pleasanter'; //const pleasanter = 'https://neo999.next-hd.net/pleasanter'; const apiKey = '6504c8a807677a3a576e10327f3c19876c55736ee45d4a845796b9e7f5e087bfd4bd0d8184863da8cf1733ca635111432ab334aea59102b06a96ee6d2c05190d'; const uploadSiteId = "126841"; //pdftotext 外部ツール const appPath = '"./poppler/Library/bin/pdftotext.exe"'; //オプション const arg = '-layout -nopgbrk'; function main() { console.log('■■■■■■■■■■■■■■■■■■■■■■■■■■'); //PDFファイル一覧を取得し、外部ツールでテキスト化する getPDFlist(); console.log('▶▶▶ PDFtoTEXT Complete'); console.log('■■■■■■■■■■■■■■■■■■■■■■■■■■'); //テキスト化したファイルをCSVに変換する getTEXTlist(); //outputDataAnalyse(pdfPath, output); } //-------------------------------------------------------------------------------------------- //PDFファイル一覧を取得し、外部ツールでテキスト化する function getPDFlist() { //pdfファイル一覧 let files = fs.readdirSync(inputDir, { withFileTypes: true }).filter(dirent => dirent.isFile()).map(({ name }) => name) //フォルダ除外 .filter(function (file) { return path.extname(file).toLowerCase() === '.pdf'; //拡張子pdfだけ }); console.log(files); files.forEach(function (file) { let fileName = path.parse(file).name; //ファイル名取得 //ファイル名が6文字(YYYYMM)の場合のみ実行する if (fileName.length == 6) { let year = parseFloat(fileName.substring(0, 4)); let month = parseFloat(fileName.substring(4, 6)); //年と月の範囲を確認し、範囲内なら実行する if (year > 2000 && year < 2100 && month >= 1 && month <= 12) { let inputPath = './' + inputDir + '/' + file; let outputPath = './' + outputDir + '/' + file.replace('pdf', 'txt'); console.log('>>> 1.TEXT抽出 処理開始------------'); //PdftoTextコマンドと連結 let cmd = appPath + ' ' + arg + ' ' + inputPath + ' ' + outputPath; console.log(cmd); //外部コマンドを実行する childProcess.execSync(cmd); console.log('-------------------------------1-DONE'); //完了後、ファイルを移動 console.log('>>> 2.Move PDF file : ' + inputPath); let completePath = './' + inputDir + '/complete/' + file; fs.renameSync(inputPath, completePath); console.log('-------------------------------2-DONE'); } } }); } function getTEXTlist() { //txtファイル一覧 let files = fs.readdirSync(outputDir, { withFileTypes: true }).filter(dirent => dirent.isFile()).map(({ name }) => name) //フォルダ除外 .filter(function (file) { return path.extname(file).toLowerCase() === '.txt'; //拡張子txtだけ }); console.log(files); //ファイル名から年と月を取得 // files.forEach(function (file) { console.log('>>> 3.CSV変換 処理開始------------') //ファイル情報取得 let fileName = path.parse(file).name; //ファイル名取得 let year = fileName.substring(0, 4); let month = fileName.substring(4, 6); let inputPath = './' + outputDir + '/' + file; let outputPath = './' + outputCsvDir + '/' + file.replace('txt', 'csv'); outputDataAnalyse(inputPath, outputPath, year, month); console.log('-------------------------------3-DONE'); console.log('>>> 4.CSVアップロード 処理開始------------') importToPleasanter(outputPath, "UTF-8", true, uploadSiteId, "Title"); }); } function outputDataAnalyse(inputPath, outputPath, year, month) { let csvData = fs.readFileSync(inputPath); let lines = csvData.toString().split('\n'); fs.writeFileSync(outputPath, '識別コード,主/副,担当者名,訪問時間,終了時間,対応時間,予防,内容,その他,クライアント,主/副担当者\n'); let sub = ""; lines.forEach(function (line) { //console.log(line); line = line.replace(/:/gm, ' '); //コロン スペース変換 line = line.replace(/~/gm, ' '); //コロン スペース変換 line = line.replace("副)", ' 副 '); //コロン スペース変換 line = line.replace(/\(/gm, ''); //カッコ削除 line = line.replace("分)", ''); //カッコ削除 line = line.replace(/^\s+/gm, ''); //行頭スペース削除 line = line.replace(/\s$/gm, ''); //行末スペース削除 line = line.replace(/\s+/gm, ' '); //多重スペース縮小 let data = line.split(/\s/); //スペースで区切り if (data.length == 1) sub = data[0]; if (data.length > 10 && data.length < 18) { if (data[1] != '副') { data.splice(1, 0, '主'); } if (data[10] == '予防') { data.splice(12, 0, sub); sub = ""; } else { data.splice(10, 0, ""); data.splice(12, 0, sub); sub = ""; } if (data.length == 15) { data.splice(16, 0, ''); data.splice(17, 0, ''); } let output = data.join(','); //カンマ保存 //if (data.length == 16) console.log(data.length + ' ' + data); //インポート用CSVデータ作成 let recordData = year + '.' + month + '_' + data[2] + data[3] + '_' + data[0] + ',' + data[1] + ',' + data[2] + ' ' + data[3] + ',' + year + '/' + month + '/' + data[4] + ' ' + data[5] + ':' + data[6] + ':00' + ',' + year + '/' + month + '/' + data[4] + ' ' + data[7] + ':' + data[8] + ':00' + ',' + data[9] + ',' + data[10] + ',' + data[11] + ',' + data[12] + ',' + data[13] + ' ' + data[14] + ','; if (data[15] != '') { recordData += data[15] + ' ' + data[16]; } //console.log(recordData); fs.appendFileSync(outputPath, recordData + '\n'); } }); } function importToPleasanter(importFile, encoding, updatableImport, siteId, key) { const url = pleasanter + '/api/items/' + siteId + '/import'; const csvData = fs.readFileSync(importFile, 'utf-8'); //送信データ let formData = new FormData(); let json = { "ApiVersion": 1.1, "ApiKey": apiKey, "Encoding": encoding, "UpdatableImport": updatableImport, "Key": key }; formData.append('parameters', JSON.stringify(json)); formData.append('file', new Blob([csvData])); fetch(url, { "method": 'POST', "body": formData }).then((response) => { if (!response.ok) { throw new Error(`${response.status} ${response.statusText}`); console.log(response); } // レスポンスが JSON 形式で返っていることを想定 return response.json(); }).then((data) => { console.log('** fetch: then(data)'); console.log(data); console.log('-------------------------------4-DONE'); }).catch((reason) => { // エラー処理 console.log('** fetch: catch'); console.log(reason); }); } /* function importToPleasanter(importFile, encoding, updatableImport, siteId, key) { const url = pleasanter + '/api/items/' + siteId + '/import'; const csvData = fs.readFileSync(importFile); //送信データ let json = { "ApiVersion": 1.1, "ApiKey": apiKey, "Encoding": encoding, "UpdatableImport": updatableImport, "Key": key }; //データ取得リクエスト const xhr = new XMLHttpRequest(); //XMLHttpRequestの作成 //HTTPリクエスト実行 xhr.open('POST', url, true); xhr.setRequestHeader('Content-Type', 'application/json;charset=utf-8'); xhr.onload = () => { //XMLHttpRequestのリクエストステータスの確認 if (xhr.status === 200) { //success let data = JSON.parse(xhr.responseText); //結果を配列に結合 resData = resData.concat(data.Response.Data); //全件取得するまで繰り返す if ((data.Response.Offset + data.Response.PageSize) <= data.Response.TotalCount) { sendRequest(data.Response.Offset + data.Response.PageSize); } else { //全件取得したら配列の各要素を処理 resData.forEach(function (value) { const result = dataCreate(value); if (!result) { console.log(value); console.log("Update Failed!!"); return; } }); } } else { //error console.log(JSON.parse(xhr.responseText)); } }; xhr.send(JSON.stringify(json)); } */ //始動 main();