当サイトの一部ページには、アフィリエイト・アドセンス・アソシエイト・プロモーション広告を掲載しています。

Amazonのアソシエイトとして、Security Akademeiaは適格販売により収入を得ています。

広告配信等の詳細については、プライバシーポリシーページに掲載しています。

消費者庁が、2023年10月1日から施行する景品表示法の規制対象(通称:ステマ規制)にならないよう、配慮して記事を作成しています。もし問題の表現がありましたら、問い合わせページよりご連絡ください。

参考:令和5年10月1日からステルスマーケティングは景品表示法違反となります。 | 消費者庁

Googleドキュメントで「セクションごとの文字数」を自動で数える方法【GAS活用編】

必要に迫られて、ボリューム感を可視化するGASスクリプトを作成しました。
まあまあ便利なので、共有することにします

Googleドキュメントで「セクションごとの文字数」を自動で数える方法

Googleドキュメントで原稿を執筆していると、章や節ごとに文字数を把握したくなることがあります。

今回紹介するのは、見出し単位(Heading 1〜3)で文字数を自動集計し、各セクションの直後に注記として挿入するスクリプトです。

機能の概要

紹介するGASスクリプトとして、以下の2つがあります。

  • カウント実行(countSectionChars)
  • クリア実行(clearSectionChars)

countSectionChars(文字数を挿入)

  • Heading 1〜3 の見出しを起点に、次の見出しまでの本文を「セクション」と定義
  • 各セクションの文字数(全角・半角・記号すべて)をカウント
  • 見出し段落自体の文字も含めてカウント
  • 通常の段落だけでなく、箇条書き(リスト)項目も対象
  • 結果は見出しの次の段落に自動で挿入
  • スタイル:グレー文字・9pt・右寄せ

clearSectionChars(注記の削除)

  • 上記で挿入された 「(このセクション:○○文字)」 という注記だけをドキュメントから削除する
  • 正規表現にマッチする注記のみ削除する
  • 他の本文に影響しない

活用できそうな場面

  • ドキュメントの章構成を確認しながら執筆する。
  • 編集者とのレビュー共有時に「この章は少ない」「ここは多すぎ」などの視覚的判断に使う。
  • 段階的な分量調整が必要な技術書執筆や商業原稿での利用に適している。

実行イメージ

以下のGoogleドキュメントがあったとします。

それぞれの実行結果は、以下のとおりです。

カウント実行(countSectionChars)

クリア実行(clearSectionChars)

カウントした文字数は、原稿に埋め込まれたまま保存されています。

表示されている文字数は自分(執筆者)のチェック用としては有用ですが、編集者に提出時には不要な情報かもしれません。

不要であれば、すべて削除する必要があります。

そこで、クリア処理のための関数も用意しました。

GAS(Google Apps Script)のソースコード

function countSectionChars() {
  const body = DocumentApp.getActiveDocument().getBody();

  let i = 0;
  while (i < body.getNumChildren()) {
    const element = body.getChild(i);

    if (
      element.getType() === DocumentApp.ElementType.PARAGRAPH &&
      [DocumentApp.ParagraphHeading.HEADING1,
       DocumentApp.ParagraphHeading.HEADING2,
       DocumentApp.ParagraphHeading.HEADING3].includes(element.asParagraph().getHeading())
    ) {
      const headingPara = element.asParagraph();
      const headingLevel = headingPara.getHeading();

      // 見出し自体の文字数もカウント
      let blockCharCount = headingPara.getText().replace(/\n/g, '').length;

      let j = i + 1;

      while (j < body.getNumChildren()) {
        const nextElem = body.getChild(j);
        const nextType = nextElem.getType();

        if (
          nextType === DocumentApp.ElementType.PARAGRAPH &&
          [DocumentApp.ParagraphHeading.HEADING1,
           DocumentApp.ParagraphHeading.HEADING2,
           DocumentApp.ParagraphHeading.HEADING3].includes(nextElem.asParagraph().getHeading())
        ) {
          break;
        }

        if (
          nextType === DocumentApp.ElementType.PARAGRAPH ||
          nextType === DocumentApp.ElementType.LIST_ITEM
        ) {
          const text = nextElem.getText().replace(/\n/g, '');
          blockCharCount += text.length;
        }

        j++;
      }

      // 見出し1 でも本文がなければ注記スキップしない(見出し含むので0文字にはならない)
      const expectedText = `(このセクション:${blockCharCount}文字)`;

      const nextIndex = i + 1;
      const nextExists = nextIndex < body.getNumChildren();
      const nextPara = nextExists ? body.getChild(nextIndex) : null;

      if (
        nextExists &&
        nextPara.getText().trim().match(/^(このセクション:\d+文字)$/)
      ) {
        if (nextPara.getText().trim() !== expectedText) {
          nextPara.setText(expectedText);
          nextPara.setForegroundColor('#888888');
          nextPara.setFontSize(9);
          nextPara.setAlignment(DocumentApp.HorizontalAlignment.RIGHT);
        }
        i = j;
      } else {
        const inserted = body.insertParagraph(nextIndex, expectedText);
        inserted.setForegroundColor('#888888');
        inserted.setFontSize(9);
        inserted.setAlignment(DocumentApp.HorizontalAlignment.RIGHT);
        i = j + 1;
      }
    } else {
      i++;
    }
  }
}

function clearSectionChars() {
  const body = DocumentApp.getActiveDocument().getBody();
  const paragraphs = body.getParagraphs();

  for (let i = paragraphs.length - 1; i >= 0; i--) {
    const para = paragraphs[i];
    const text = para.getText().trim();

    // 「(このセクション:○○文字)」の形式に完全一致する段落を削除
    if (text.match(/^(このセクション:\d+文字)$/)) {
      body.removeChild(para);
    }
  }
}

※この記事中のコードは初期バージョンです。最新版はGitHubで公開しています。
GitHubリポジトリはこちら

実行方法【GAS未経験者向け】

1:Googleドキュメントのメニューの「拡張機能」>「Apps Script」を選ぶ

2:上記のコードを貼り付けて保存する

※App Script名は適切なものに変更して構いません。

3:文字カウントを挿入したい場合は、上部の関数選択から「countSectionChars」を選んで「▶ 実行」を押す

※初回はGoogleアカウント認証を行う必要があります。その際、以下の「このアプリはGoogleで確認されていません」という画面が出るかもしれません。

4:挿入した文字カウントを削除したい場合は、「clearSectionChars」を実行する

「このアプリはGoogleで確認されていません」という画面が表示された

以下の画面は、Google Apps Scriptを初めて実行する際によく出る確認画面です。

このスクリプトはまだ「Google によって検証されていない」ため、セキュリティ警告が表示されます。ただし、自分自身で作成したスクリプト(自分の Google アカウント内)であれば安全です。

この画面を突破するには、「詳細」リンクをクリックします。下のほうに「(自分のプロジェクト名)に移動」と出るので、それをクリックします。その後、次の画面で「許可」を押せば完了です。

一度承認すれば、同じスクリプトではこの確認は表示されなくなります。ただし、スクリプトを大幅に変更したときは再度出ることがあります。