Notes

アンケートのクロス集計から
報告書PDFを自動生成するまで

クーポン企画で本当に時間を食うのは、開催中ではなく開催後です。

回答をExcelに写して、ピボットテーブルで年代別を出して、 そこから円グラフを作って、パワーポイントに貼って、 前年の資料を引っ張り出して数字を並べる。これで数週間が消えます。しかも毎年ほとんど同じ作業をしています。

管理画面のボタン1つでA4横のPDFが出るようにしました。その過程の記録です。

まず、集計を「表の組」として定義する

報告書に載る図は、突き詰めると全部クロス集計です。 年代別の内訳も「年代 × 全体」ですし、年代×性別も、居住地×年代も同じ形をしています。

そこで、行に置く設問と列に置く設問を選ぶと、表の組が出てくる関数を作りました。

  • 表1: 行軸 × 列軸(例: 年代 × 性別)
  • 表2以降: 軸に使っていない選択式の設問ごとに「× 行軸」と「× 行軸 × 列軸」

この関数はデータベースに触りません。設問の一覧と回答の一覧を受け取って、表を返すだけです。 そうしておくと、同じ関数を管理画面の表示・Excel出力・PDF生成の3箇所で使い回せます。集計ロジックが3箇所にあると、必ずどれかがずれます。

落とし穴1: ラベルの種類が回答者の入力で増える

最初の実装は、回答された値をそのままラベルにしていました。これが良くなかった。

自由入力の設問や、選択肢を後から変更した設問があると、表の列数が回答者の入力次第で際限なく増えます。 Excelに出したときに横に100列並ぶ。しかも、入力された文字列がそのまま管理画面に出てしまう。

いまは、ラベルの種類を「管理者が定義した選択肢」の範囲に閉じています。 定義に無い値はその他に、回答していない人は未回答にまとめる。 列が増えないだけでなく、前年の表と列がそろうという副次的な効果もありました。

落とし穴2: 複数選択があると合計が人数と合わない

「あてはまるものをすべて選んでください」という設問では、 1人が3つ選べば3回数えられます。行の合計が回答者数を超える。

これを「バグ」として合計を人数に合わせてしまうと、今度は選択率が正しくなくなります。 正解は、合計が超えることを正常として扱い、そう見えるように出すことでした。 表には回答者数を別に持たせて、パーセントは回答者数を分母に出しています。

PDFは「1ページ=1テーマ」で固定する

出力はA4横の7ページ構成にしています。1ページに1つのテーマだけを置く。 報告会で1枚ずつめくって話せる形が、結局いちばん使われます。

レイアウトはミリメートルで直接指定しています。 レスポンシブに考える必要がないぶん、Webより簡単に思えますが、実際は逆でした。紙は伸びないので、はみ出したら終わりです。

たとえば、円グラフを左半分に置いて右に凡例を出す案を試したのですが、 凡例の「はい 4,605名(77.6%)」という行が枠に収まりませんでした。 幅を半分にすると文字も小さくなるので、読めなくなる。 結局、円を上に低く敷いて、その下に横棒を2枚並べる形に落ち着いています。

落とし穴3: グラフの文字が同じ大きさにならない

グラフはSVGで描いてから画像にしてPDFに貼っています。 このとき、全幅のグラフも半幅のグラフも同じ論理サイズ(1200px)で描いてしまうと、 半幅のほうは紙の上で半分に縮むので、文字だけが半分の大きさになります

いまは「1ミリメートルあたり何ピクセルか」を1つ決めて、 枠のミリ幅からSVGのピクセル幅を計算しています。 こうすると、どの大きさの枠でも同じフォント指定が同じ物理サイズになります。

const PX_PER_MM = 1200 / (PAGE.w - MARGIN * 2)
const width = Math.round(box.w * PX_PER_MM)

落とし穴4: 区分が多い設問で棒グラフの文字が重なる

居住地のように区分が15個ある設問だと、横棒が細くなって、 ラベルと数値が上下で重なりました。 棒の本数に応じて行の高さと文字の大きさを決めるようにして解決しています。 「グラフは固定サイズ」という前提を捨てるのが遅れた例です。

67MBのPDFが出た話

いちばん派手に失敗したのはここです。完成したPDFを開いたら67MBありました。 メールで送れません。

原因は、画像をPDFに貼るときの圧縮指定を省略していたことでした。 省略すると、PNGとして渡した画像が展開された生のRGBデータのまま格納されます。 PDFの中身を見ると、圧縮されたデータの塊が1つも入っていませんでした。

圧縮を指定するよう1行足したら1.56MBになりました。53分の1です。 しかもこれは可逆圧縮なので、画質は1ピクセルも落ちていません。 念のため、PDFの中の画像を全部取り出して展開し、 もとの画像と同じバイト数になることを確かめました。

「圧縮されているだろう」と思い込んでいたところが、まったく圧縮されていなかった。 出力物のサイズは、動くかどうかとは別に一度は見たほうがいい。

いまはテストで、生成したPDFの中に圧縮されたデータが存在することを検査しています。 このテストを書くとき、1ピクセルの画像だと圧縮が働かず素通りしてしまったので、 テスト内で200×200の本物のPNGを組み立てて渡しています。

前年比較は「入れておけば出る」ようにする

報告書でいちばん喜ばれるのは、前年との比較です。 「昨年より20代が増えた」が言えるかどうかで、次の企画の説得力が変わります。

ただ、前年のデータは大抵システムの外にあります。紙の資料しか残っていないことも多い。 なので、前年の設問ごとの件数を管理画面から手で登録できるようにして、登録されていれば各ページに自動で前年比が入る形にしました。 登録されていなければ、比較の欄が消えるだけで、それ以外は変わりません。

結果として何が変わったか

開催が終わった翌日には、報告資料の材料が揃っています。 集計担当を立てる必要がなくなり、数字を写し間違える経路が消えました。

そして副次的な効果として、開催中に同じPDFが出せるようになりました。 中間報告を求められたときに、その場で出せる。 最初は「終了後に作るもの」として設計していたので、これは後から気づいた利点でした。

ほかの開発記録

ハレポンは、ここに書いた仕組みをそのまま使えるクーポン発行システムです。 企画設計から報告書の提出までお引き受けしています。できること料金もご覧ください。

資料をダウンロード相談する