「ちな、7,000件な!」
さすがに手入力はやってられん。という事で、Node.js で自動化してみました
※ 完成品はこちら
テスト環境の下準備
Node.jsはインストール済みで
最低限のjs知識がある方を前提としています
プロジェクトの作成
任意のディレクトリを作成してnpm init
しましょう
入力項目は任意で決めて大丈夫です
mkdir excel-replaceer
cd excel-replaceer
npm init
モジュールのインストール
今回使用するモジュールはfs
とxlsx
の2つです
fs : https://www.npmjs.com/package/fs
xlsx : https://www.npmjs.com/package/xlsx
npm install fs
npm install xlsx
テスト用のExcelファイルの作成
読み込んでくるtest.xlsx
ファイルを作成します
今回はプロジェクト直下に/test
というディレクトリを作成し
そこに読み込んでくるExcelファイルと置換するhtmlファイルを設置します
今回、Excelのデータ内容は下記の様な感じで作成します
A | B | C | |
---|---|---|---|
1 | test01.html | dummy | test01 |
2 | test02.html | dummy | test02 |
3 | test03.html | dummy | test03 |
テスト用のhtmlファイルの作成
今回のテストで置換するhtmlファイルを作成します
『A列』に記載がある通りの名前でhtmlを3つ作成してください
ディレクトリはExcelファイルと同様/test
配下に保存します
htmlファイルの中身は任意で決めてもらえばよいですが、
今回は『B列』の「dummy」を置換するのでどこかしらにdummyを記述してください
<!DOCTYPE html><htmllang="en"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>dummy</title></head><body></body></html>
これでテストを行う為の下準備は完了です
モジュール作成
次は実際にExcelから情報を取得して、置換処理を行うまでの解説です
index.js
の作成
プロジェクト直下にindex.js
を作成してください
ここに実際の置換処理を書いていきます
node module
の読み込み
下準備の段階でインストールを行ったfs
とxlsx
を使用するので
この2つを呼び出して、いつでも使えるように変数に格納します
constxlsx=require('xlsx');constutils=xlsx.utils;constfs=require('fs');
utils
はxlsx
の機能の一つで、こちらも毎回呼び出す手間を省く為に
変数に格納しています
これでモジュールを使う準備ができました
Excelファイルの読み込み
Excelファイルの操作はxlsx
モジュールを使用して行います
// 上部 略consttestX=xlsx.readFile('./test/test.xlsx');constsheet=testX.Sheets['Sheet1'];
readFile
を使用することによってExcelファイルの読み込みができます
読み込んだExcelの内容をtextX
に格納し、その中のSheet1
の情報をsheet
変数に格納しています
セルの値を取得する為にはsheet['A1']
というように
シート情報からセル名を指定して取得してきますが、
今回は入力されている範囲を取得して、ループを回してデータを取得します
範囲の取得
// 上部 略constrange=sheet['!ref'];constrangeN=utils.decode_range(range);
次にシートの記載がある範囲を取得します
先ほどシートの情報を格納したsheet
変数から['!ref]
を指定すると
範囲が取得できるので、こちらをrenge
の変数に格納します
今回の場合、range
には『A1:C2』が入っています
範囲を取得することはできましたが、今取得してきた範囲は
テキストデータになっている為、A列からC列までループ処理は回せません
これを解決するためにutils
を使用していきます
utils
のdecode_range()
を使用して、先ほどとってきたテキストデータの
範囲を渡してあげる事で、詳細な範囲データを返してくれます
これをrangeN
に格納しています 中身は下記の様になっています
{s:{c:0,r:0},e:{c:2,r:1}}
それぞれ情報内容はこんな感じ
key | 情報 |
---|---|
s | スタートのセル情報 |
e | エンドのセル情報 |
c | 列 (A, B, C ~~) の情報 |
r | 行 (0, 1, 2 ~~) の情報 |
この情報を利用すれば、ループ分を回して行数分実行したり
列分実行したり、全レコード分実行したりできます
今回は『B列』に元データ『C列』に変更後データがある状態を想定して作るので
行数分、置換が実行できれば良いことになります
ループ・置換処理
今回は『A列』に置換したいファイル名が記載されており
『B列』に変更前の文字列、『C列』に変更後の文字列が記載されているので
行数分、置換処理を実行すれば良いことになります
for文
で行数分ループするようにしましょう
// 上部 略for(letr=rangeN.s.r;r<=rangeN.e.r;r++){letaddress=utils.encode_cell({c:0,r:r});letcell=sheet[address];}
for(letr=rangeN.s.r;r<=rangeN.e.r;r++)
でrangeN.s.r
のスタートの行番号から、rangeN.e.r
のエンドの行番号までループする処理を書きます
次にセルの情報を取得してきます
『A列』に置換したいファイル名が記載されているので
列のインデックス番号であるc
をc:0
で固定して編集するファイルを取得しましょう
letaddress=utils.encode_cell({c:0,r:r});letcell=sheet[address];
utils
のencode_cell()
を使用することでc
とr
のプロパティで
指定されたセルを、テキストベースに変換してくれます
let address = utils.encode_cell({c:0, r:0});
の場合は、addressに「A1」が入ります
これで、cell
に『A列』のデータ(ファイル名)が入るように設定できました
指定のファイルを読み込んでみましょう
// fs.readFile([読み込むファイルのパス], [読み込む文字コード], [コールバック関数]); fs.readFile('./test/'+cell.v,'utf-8',(err,data)=>{// エラー処理if(err){console.log(`【 ${cell.v}】ファイル読み込みエラー`);throwerr;}});
ファイルの読み書きにはfs
モジュールを使用します
ファイルの読み込みではreadFile()
を使用します
上記のように、簡単なエラー処理も書いておきましょう
このコールバック関数内で、置換の処理を行っていきます
コールバック関数で渡しているdata
には取得してきた内容が入っています
// 変更前の内容を取得letB_address=utils.encode_cell({c:1,r:r});letB_cell=sheet[B_address];// 変更後の内容を取得letA_address=utils.encode_cell({c:2,r:r});letA_cell=sheet[A_address];// 置換constbeforeTxt=data;constafterTxt=beforeTxt.replace(newRegExp(B_cell.v,"g"),A_cell.v);
今回は『B列』に変更前の文字列、『C列』に変更後の文字列が
入っていることがわかっているので、それぞれ『A列』の情報を
とってきた時と同様に、c
プロパティを固定して情報を取ってきます
あとはおなじみのreplace()
を使用して置換をおこないafterTxt
に格納しておきます
// fs.writeFile([書き込むファイルパス], [書き込む内容], コールバック関数)fs.writeFile('./test/'+cell.v,afterTxt,(err)=>{if(err){console.log(`【 ${cell.v}】ファイル置換エラー`);throwerr;}console.log(`【 ${cell.v}】success !`);});
最後にファイルの上書きを行っていきます
ファイルの書き込みにはwriteFile()
を使用します
こちらにも簡単なエラー処理を書いてあげましょう
index.js
の完成形はこんな感じ
// モジュールのインストールconstxlsx=require('xlsx');constutils=xlsx.utils;constfs=require('fs');// エクセルファイルの読み込みconsttestX=xlsx.readFile('./test/test.xlsx');// シートの読み込みconstsheet=testX.Sheets['Sheet1'];// セルの範囲の取得constrange=sheet['!ref'];// console.log(range);// セルの範囲を数値化constrangeN=utils.decode_range(range);// ループ処理for(letr=rangeN.s.r;r<=rangeN.e.r;r++){// ファイル名取得letaddress=utils.encode_cell({c:0,r:r});letcell=sheet[address];// htmlの読み込みfs.readFile('./test/'+cell.v,'utf-8',(err,data)=>{// エラー処理if(err){console.log(`【 ${cell.v}】ファイル読み込みエラー`);throwerr;}// 置換処理// 変更前の内容を取得letB_address=utils.encode_cell({c:1,r:r});letB_cell=sheet[B_address];// 変更後の内容を取得letA_address=utils.encode_cell({c:2,r:r});letA_cell=sheet[A_address];// 置換constbeforeTxt=data;constafterTxt=beforeTxt.replace(newRegExp(B_cell.v,"g"),A_cell.v);// ファイルの上書きfs.writeFile('./test/'+cell.v,afterTxt,(err)=>{if(err){console.log(`【 ${cell.v}】ファイル置換エラー`);throwerr;}console.log(`【 ${cell.v}】success !`);});});}
これで処理は完成しました!
処理の実行
最後に下記で実行して置換が行われるか試してみてください
node index.js