初めに
ServiceNowのWorkspaceにある標準機能のエクスポートでExcelだと列数制限があるとか聞いたのでその回避方法を探してみたところServiceNowでもExcelが生成できるという記事を見たので実際に試してみました。
テーブル作成
スコープとかは前の記事のものを使います。
適当にテーブルを作成して、1~100までの列を作成します。

次にUX List Categoryを作成して、リストから一覧表示できるようにします。

次にUX Listを作成します。

1~100まで表示するようにしておきます。
これでリスト表示が出来たので適当に1件レコードを作成して、エクスポートを試してみます。
普通にエクスポートされるので、あれ?と思いますが
ダウンロードされたファイルを見てみると列数は50までになっているようです。

Excel のエクスポートは、50 万セル未満の比較的小規模なエクスポートを対象としています。CSV はより大規模なエクスポートを処理できます。
エクスポート制限を見てみるとセル数は明記されているのですが列数についての制限は探してもよくわかりませんでした。Now Developerに聞いてみても明記まではたどり着けずでした。
何かしらプロパティがありそうですが、よくわからないのでスクリプトで50列以上のエクセルを作成できるのか試してみます。
List Action作成
Add a Button to the List Component using Declarative Actionsを参考にしてList Actionを作成します。
※ここからなぜかStudioだとうまくいかなかったので、Platform側で作成します。
Create New ActionからList Actionを作成します。

Action AssignmentからAction Payload DefinitionをApplicable ToをListにして作成します。

次にUX Actions Configurationを作成します。

関連リストのList ActionsからM2m Action Assig Ux Action Configを通してLinkします。

ここまで来たらWorkspaceのList画面を開くとボタンが追加されている事を確認できます。

Excel生成スクリプト
ここからスクリプトを記述して
ボタンが押されたらエクセルを生成して添付ファイルへ出力するようにします。
少し雑ですがこんな感じです。
function getColumns(tableName) {
const cols = [];
const dict = new GlideRecord('sys_dictionary');
dict.addQuery('name', tableName);
dict.addQuery('internal_type', '!=', 'collection');
dict.query();
while (dict.next()) {
cols.push(dict.getValue('element'));
}
return cols;
}
try {
const targetTableName = 'x_1603370_merryc_0_excelexporttest';
const tableGr = new GlideRecord(targetTableName);
tableGr.query();
// エクセル出力用の文字列保持変数
let output = "";
// フィールド名一覧を取得
const columnNameList = getColumns(targetTableName);
// ヘッダー行作成
output += "<Row>";
columnNameList.forEach(function(columnName) {
output += `
<Cell ss:StyleID="BoldHeader">
<Data ss:Type="String">${columnName}</Data>
</Cell>`;
});
output += "</Row>";
// データ部生成
while (tableGr.next()) {
output += "<Row>";
columnNameList.forEach(function(columnName) {
const value = tableGr.getValue(columnName) || "";
output += `
<Cell ss:StyleID="Default">
<Data ss:Type="String">${value}</Data>
</Cell>`;
});
output += "</Row>";
}
const excelFormat =
`<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet"
xmlns:x="urn:schemas-microsoft-com:office:excel"
xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet">
<Styles>
<Style ss:ID="BoldHeader">
<Font ss:Bold="1"></Font>
</Style>
<Style ss:ID="Default" ss:Name="Normal">
<Alignment ss:Vertical="Center"/>
<Font ss:FontName="游ゴシック" x:CharSet="128" ss:Size="12" ss:Color="#000000"/>
</Style>
</Styles>
<Worksheet ss:Name="Sheet1">
<Table>
${output}
</Table>
</Worksheet>
</Workbook>`;
// 添付ファイル用にレコードを作成する
const gr = new GlideRecord(targetTableName);
gr.initialize();
const tempSysId = gr.insert();
// 添付ファイルを作成
var gsa = new GlideSysAttachment();
const attachmentSysId = gsa.write(gr, "example.xls", "application/vnd.ms-excel", excelFormat);
gs.info(`attachmentSysId: ${attachmentSysId}`);
} catch (ex) {
gs.error(ex);
}
本当は出力用の別テーブルとかを持っておくべきなのでしょうが、面倒なのでテーブルに添付ファイル用のレコードを生成して添付するようにしています。
適当にレコードを作っておいてListアクションExcel Exportを押します。

添付ファイル欄にエクセルが添付されているのでダウンロードして開けるか確認します。

xmlがちゃんと作れていないのか破損の警告が出てきます。
気にせずはいを押すと一応ファイルとして開くことが出来ます。

一応きちんとエクセルの形にはなっていて、107列あることも確認できます。

終わりに
一応(?)ServiceNowでエクセルを生成する事が出来ました。
今回は手抜きでServerSideだけにしましたが、ClientScriptにして処理はScriptIncludeにしておくと一時レコードも削除できます。
また、xmlをもっと丁寧に作れば破損とかもなくなると思います。
今回はクラスにはしていないですが、Excel生成用のクラスを作って再利用可能にしておくと便利かなと思います。
まあ、ServiceNowでエクセル生成が必要になるケースがどれくらいあるのかわかりませんが。。。
参考URL
以下のURLを参考にしました。有益なサイト達に感謝します。
how can i export data into excel [.xlsx] via script
サーバーサイドスクリプトでExcel(XLS)ファイルを作成する方法
GlideRecordオブジェクトからすべての値(フィールド)を取得する
Add a Button to the List Component using Declarative Actions






