概要
全銀データ形式でデータを出力する必要があり、Visualforceで実装した。
MIMEタイプがtext/plain
形式(拡張子が「.txt」)で文字コードをShift-JISで出力する必要があった。
MIMEタイプがcsv
形式で文字コードをShift-JISで出力するケースはよくあるが、plainテキスト形式で出力するのはあまりないと思われる。
今回色々試行錯誤して一つの実現方法にたどり着いたので、こちらに備忘として記録する。
やりたいこと
- Salesforceから下記の出力形式を設定し、全銀データ形式でデータを出力する
- 出力形式
- MIMEタイプ:text/plain
- 文字コード:Shift-JIS
課題
- plainテキストはcsvやExcelのように
<apex:outputText>
タグでダウンロードできない。(普通に出力内容が画面に表示されてしまう) - LWCやVisualforce内でJavascriptを使って
<a>
タグ要素を用いてダウンロードリンクを作って、普通にダウンロードすると文字コードはUTF-8などのUnicodeで扱われてしまう(参考)
解決方法
- 外部ライブラリを使用する
- 使用するライブラリ
encoding.js
- ライブラリのREADME_ja.mdから簡単な説明を引用
encoding.js は、文字コードの変換や判定をする JavaScript ライブラリです。
Shift_JIS や EUC-JP、ISO-2022-JP など日本語の文字コードや、 UTF-8、UTF-16 などの Unicode に対応しています。
実装
- LWCからダウンロードボタン押下時にテキストファイルを出力する
lwc
const windowFeatures = 'left=100,top=100,width=320,height=320'
// ダウンロード後にページを削除するためポップアップを使用
window.open('/apex/ExportBankData', 'データ出力', windowFeatures)
- window.open関数によって開かれたVisualforceページが読み込まれた際にApex=>JSで定義した関数を実行させたいので、addEventListenerのDOMContentLoadedイベントにハンドラーを設定
- やっていること
- 出力する文字列を文字コード(Unicode)に変換
- Unicode=>Shift-JISに変換
- 文字コードをバイト配列に変換してblobデータを作成
- aタグ要素を作成して、ダウンロード
- ポップアップした新規ウィンドウを閉じる
ExportBankData.page
<apex:page controller="ExportBankDataController" cache="false" readOnly="true">
<!-- cdnでライブラリをインポートする -->
<apex:includeScript value="https://unpkg.com/encoding-japanese@2.1.0/encoding.min.js" />
<div style="display: none;">
<apex:form>
<apex:actionFunction name="initAction" action="{!doExport}" oncomplete="doExport('{!fileName}', '{!fileData}', '{!mimeType}');"
/>
</apex:form>
</div>
<script>
document.addEventListener('DOMContentLoaded', function () {
initAction(); // actionFunctionを呼び出す
});
function doExport(fileName, fileData, mimeType) {
// データがないなら処理を実行しない
if (!fileData) {
return;
}
// 文字列から文字コード値の配列に変換
const unicodeArray = Encoding.stringToCode(fileData);
// Shift-JISのバイト配列にエンコード
const sjisArray = Encoding.convert(unicodeArray, 'SJIS', 'UNICODE');
// バイト配列からBlobオブジェクトを生成
// Uint8Array:0~255の値を格納するTypedArrayオブジェクトの一つ
const blobData = new Blob([new Uint8Array(sjisArray)], { type: mimeType });
// ダウンロードを実行
const link = document.createElement("a");
link.download = fileName;
link.href = window.URL.createObjectURL(blobData);
link.click();
URL.revokeObjectURL(link.href);
window.close();
}
</script>
</apex:page>
- 出力するデータやファイル名、Mimeタイプなどを設定する
ExportBankDataController
public with sharing class ExportBankDataController {
public String fileName { get; set; }
transient public String fileData { get; set; }
public String mimeType { get; set; }
public ExportBankDataController() {
}
public void doExport() {
this.fileData = 'ホゲホゲ';
this.fileName = 'hogehoge.txt';
this.mimeType = 'text/plain';
}
}
動作確認
-
文字コードの確認は、encode.jsが用意しているファイルから文字コードを判定するツールを使用
まとめ
今回はユースケースとしては少ないと思われるため、参考記事があまりない中で辿り着いた解決方法を記載しました。なので、おそらく他にもっとより良いやり方もあるのでは?と思っています。
私と同様の要件で出力する必要などがあり、困っている方の一助になれば幸いです。