GAS(Google Apps Script)を使って、Googleドキュメント上の文章の表記統一(一括置換)および表記チェック(要チェック箇所の文字色を変えて表示)ができるスクリプトです。以前に公開していたバージョンの改良版です。正規表現対応。
正規表現が利用可能。編集者やライター、広報や社内文書の担当者、ブロガーなど向け。使い方とカスタマイズ方法の解説記事もあわせて参照してください。
前バージョンからの変更点
- 一括置換と表記チェックをまとめて1回の操作で行うようにしました
- 上記にあわせて、置換・チェックのテーブルを1つのスプレッドシートにまとめました
- 置換した文字の色も変え、「ここを置換した」と分かるようにしました
- 半角スペースのチェック機能を追加しました
- 「Heartlogic Proofreader for GDocs」と名前を付けました
機能と特徴
- Googleドキュメントの文書に対して、表記統一のための一括置換と、要確認の文字列のチェック(検出)を同時に行います。置換後の文字列、チェックした文字列は色を変えて目印とします
- Googleドキュメント上で目視確認しにくい半角スペースをチェックし、半角スペースを目視可能にします(半角スペースがある箇所の背景色を変更)
- 一括置換および表記チェック用のテーブル(対象文字列の一覧)はGoogleスプレッドシートで管理でき、カスタマイズが容易です
- 置換および表記チェックには正規表現が利用できます
- 正規表現に詳しくない人向けに、表記チェックでは非正規表現も利用できます(エスケープなどの処理が不要)
- 下のスクリーンショットのようにメニューバーからスクリプトを呼び出せるので、操作が簡単です
導入方法とコード
以下のコードをコピーして、Googleドキュメントのスクリプトエディタに貼り付けてください(183行)。詳しい方法はコードの下にて。
//Heartlogic Proofreader for GDocs(Googleドキュメント 一括置換&表記チェック) //Yuichiro Kobayashi 2022.2.27 Ver.1.0 //heartlogic.jp@gmail.com //初期設定 const sSheetid = '1Lk2ZP86std_iebNlebeeT7pHUWKc4r9lnMBuNSS5Ac4'; //スプレッドシートのID const checkHalfSpaces = 1; //半角スペースをチェックする場合は1 const rColor = '#3300ff'; //置換した文字の色 const cColor = '#ff0000'; //表記チェック箇所の文字の色 const sColor = "#ffff66"; //半角スペースの背景色 //メニュー追加 function onOpen() { const ui = DocumentApp.getUi() const menu = ui.createMenu("簡易校正"); menu.addItem("簡易校正を実行","ReplaceWords"); menu.addToUi(); } //簡易校正ツール本体 一括置換およびチェック function ReplaceWords(){ //スプレッドシートから置換・チェック用テーブル「replaceTexts」を取得 const ss = SpreadsheetApp.openById(sSheetid); //IDを設定 const sh = ss.getActiveSheet(); const lastRow = sh.getLastRow(); const replaceTexts = sh.getRange(1,1,lastRow,3).getValues(); //アクティブなドキュメントの本文を変数「docBody」として取得 const doc = DocumentApp.getActiveDocument() const docBody = doc.getBody(); const docasText = docBody.asText(); const docText = docBody.getText(); //本文を置換 or チェック(テーブルの行数分ループ) for (let i=0;i<lastRow;i++) { const cWord = String(replaceTexts[i][0]); const rWord = String(replaceTexts[i][1]); //置換かチェックか?(B列に文字列はあるか?) if(rWord !== ''){ //置換→正規表現か非正規表現か(C列を判定) if(replaceTexts[i][2] !== 1){ //正規表現による置換 //正規表現パターンを設定 let regxOp = null; if(replaceTexts[i][2] == 'i'){ regxOp = 'igm'; }else{ regxOp = 'gm'; } const cMatch = new RegExp(cWord, regxOp); //ポジションを初期化 let pos = 0; let posL = 0; //置換実行、色設定 while((arry = cMatch.exec(docText)) !== null){ //除外文字(仮称)を使う、かつ除外文字のマッチがあった場合、その文字を置換対象の末尾から取り除く if(replaceTexts[i][2] == 2 && RegExp.$1 !== ''){ const mLen = arry[0].length-RegExp.$1.length; arry[0] = arry[0].substring(0,mLen); } //置換実行、文字色変更 posL = docBody.asText().getText().indexOf(arry[0], pos); if(posL !== -1){ docasText.deleteText(posL,posL+arry[0].length-1); docasText.insertText(posL,rWord); docasText.setForegroundColor(posL,posL+rWord.length-1,rColor); } pos = cMatch.lastIndex; } }else{ //非正規表現による置換 //マッチ数を計算、ポジションを初期化 const cSplit = docText.split(cWord); let pos = 0; let posL = 0; //マッチ位置を進める文字数を設定 let mLength = rWord.length -1; if(mLength == 0){ mLength = 1; } //置換実行、文字色変更 for(let ii=0;ii<cSplit.length;ii++){ posL = docBody.asText().getText().indexOf(cWord, pos); if(posL !== -1){ docasText.deleteText(posL,posL+cWord.length-1); docasText.insertText(posL,rWord); docasText.setForegroundColor(posL,posL+rWord.length-1,rColor); } pos = posL+mLength; } } }else{ //チェック→正規表現か非正規表現か(C列を判定) if(replaceTexts[i][2] !== 1){ //正規表現によるチェック //正規表現パターンを設定 let regxOp = null; if(replaceTexts[i][2] == 'i'){ regxOp = 'igm'; }else{ regxOp = 'gm'; } const cMatch = new RegExp(cWord, regxOp); //ポジションを初期化 let pos = 0; let posL = 0; //チェック実行 while((arry = cMatch.exec(docText)) !== null){ //除外文字(仮称)を使う、かつ除外文字のマッチがあった場合、その文字をチェック対象の末尾から取り除く if(replaceTexts[i][2] == 2 && RegExp.$1 !== ''){ const mLen = arry[0].length-RegExp.$1.length; arry[0] = arry[0].substring(0,mLen); } //文字色変更 posL = docBody.asText().getText().indexOf(arry[0], pos); if(posL !== -1){ docasText.setForegroundColor(posL,posL+(arry[0].length-1),cColor); } pos = cMatch.lastIndex; } }else{ //非正規表現によるチェック //マッチ数を計算、ポジションを初期化 const cSplit = docText.split(cWord); let pos = 0; let posL = 0; //マッチ位置を進める文字数を設定 let mLength = cWord.length -1; if(mLength == 0){ mLength = 1; } //チェック実行および文字色変更 for(let ii=0;ii<cSplit.length;ii++){ posL = docBody.asText().getText().indexOf(cWord, pos); if(posL !== -1){ docasText.setForegroundColor(posL,posL+cWord.length-1,cColor); } pos = posL+mLength; } } } } //半角スペースをチェックするか? if(checkHalfSpaces == 1){ //半角スペースを検出 const cWord=' '; const cSplit = docText.split(cWord); let pos = 0; let posL = 0; //マッチ位置を進める文字数を設定 const mLength = 1 //チェック実行、色設定 for(let ii=0;ii<cSplit.length;ii++){ posL = docBody.asText().getText().indexOf(cWord, pos); if(posL !== -1){ docasText.setBackgroundColor(posL,posL,sColor); } pos = posL+1; } } }
Googleドキュメントの編集画面で、メニューの[ツール]-[スクリプトエディタ]を選択すると、別のタブでスクリプトエディタが表示されます。
コピーしたコードを、上の画面のように貼り付けます。スクリプトエディタが表示された時点で「function myFunction() {~」と3行分のコードが入っていますが、それは削除したうえで貼り付けてください。現在公開しているコード(Ver.1.0)を貼り付けると、全部で183行になります。
初期設定ではサンプルの簡易校正用テーブルを利用するよう設定しています。独自のテーブルを作成したら、スクリプトの6行目「const sSheetid = ‘1Lk2ZP86std_iebNlebeeT7pHUWKc4r9lnMBuNSS5Ac4‘; 」の、赤字で示した部分を、そのテーブルのIDに置き換えてください。
IDとは、Googleスプレッドシートを開いたときのURL「https://docs.google.com/spreadsheets/d/○○○○/」の「○○○○」にあたる部分です(半角英数字44文字)。
サンプルのテーブルはこちらです。詳しくは使い方とカスタマイズ方法の解説記事も参照してください。
Heartlogic Proofreader for GDocs 簡易校正用テーブル
コードの貼り付け(およびテーブルのIDの設定)が完了したら、[保存]して[実行]します。初回実行時は許可を求められるので、画面の指示に従い許可してください。一般の(無料の)Googleアカウントの場合、[承認が必要です]というメッセージが表示されたら[権限を承認]をクリックし、続けてアカウントを選択後、怪しい画面が表示されたら[詳細]-[○○(安全ではないページ)に移動]をクリックしてください(以下の画面)。
次の画面で[許可]をクリックすると、実行が承認されます。Google Workspaceの場合は設定によって承認の操作が異なる可能性があります。
注意点など
複数のドキュメントで使いたい場合は、スクリプトがあるドキュメント自体をコピーするか、別のドキュメントにコードをコピペして使ってください。ドキュメントごとに初回起動時は許可の操作が必要です(面倒)。
バグ報告等はTwitterの@heartlogicまでお願いします(技術力不足でご期待どおりに対応できない可能性があります)。
半角記号「!?」を対象に、正規表現を使わず置換しようとすると「Exception:終了インデックス(-1)には、開始インデックス(-)以上の値を指定する必要があります。」というメッセージが表示されます。C列に「1」を指定して、正規表現を使わないようにすることで、この問題を回避できます。(2022.3.13追記)
余談
このスクリプトはもともと、GASのreplaceTextメソッド(正規表現による文字列の置換機能)を使って編集作業を補助するツールを作ろう、ということで開発に着手しました。そうして、ある程度できあがったところで公開したのが前バージョンでしたが、ツールとしての使いやすさを追求して改善した結果、ソースの中からreplaceTextメソッドが消えました。
置換するだけじゃなくて、「ここを置換した」と目印を付けたい(置換後の文字色を変えたい)と思うとreplaceTextの機能ではうまくいかず、似た処理を自分で書き起こすことになった次第で、まあ、よくあることでしょう…(?)。
高速化の工夫はまったくできておらず、今後、そのための方法を学ぶ機会があれば、と思っています。
バージョン履歴
・2022.2.27 バージョン1.0公開