1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ServiceNowでExcel(XLS)ファイルを作成する方法【List Action】

1
Posted at

初めに

ServiceNowのWorkspaceにある標準機能のエクスポートでExcelだと列数制限があるとか聞いたのでその回避方法を探してみたところServiceNowでもExcelが生成できるという記事を見たので実際に試してみました。

テーブル作成

スコープとかは前の記事のものを使います。
適当にテーブルを作成して、1~100までの列を作成します。
image.png

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

image.png

次にUX Listを作成します。
image.png
1~100まで表示するようにしておきます。

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

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を作成します。
image.png

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

image.png

image.png

image.png

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

image.png

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

image.png

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

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を押します。
image.png

1行生成されるので、そのレコードを開きます。
image.png

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

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

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

終わりに

一応(?)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

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?