セクションの展開/省略の状態を記憶しておくJavaScriptを埋め込んだCognos レポートのサンプル


#はじめに
タイトルの通りです。
JavaScriptを使ってHTMLのdisplay=none / block を切替え、ある一定範囲のセクションを展開したり閉じたりしたりするレポートを開発していることは良くあると思います。
そんな中、レポートの再描画が発生してもセクションの展開/省略状態を覚えておきたいという要件がありサンプルのレポートを作成しましたので紹介します。
※ここではレポートの再描画を、検索のプロンプトの「検索」ボタンを押すとか、プロンプトボタンの「再プロンプト」を押すなどで、レポート画面が更新させる処理を言っています。

#サンプルレポートについて
プロンプトページとレポートページと作成していますが、基本的な内容は同じです。
※プロンプトページでも稼動するか検証したくてプロンプトページを作成しました。
※オブジェクトのID (名前) が一意になる必要があるため、その部分だけ差異がでています。

レポート内には2箇所処理を埋め込んでおり、実行されるタイミングが異なります
1. レポート実行時や再描画時のレポートHTML生成時に実行されるscriptタグ
    → レポート最下部のHTMLアイテムに記述
2. 展開/省略を切り替えるボタンが押されたタイミングで実行される埋め込みfunction
    → レポート最上部のHTMLアイテムに記述


# 簡単な仕様
・各セクションの展開/省略を状態を"0" (省略)、"1" (展開)として判別します
・テキストのプロンプトの値として0/1のコードを保持しています
・制御したいエリアが複数ある場合は桁数を増やして対応できます
・レポート実行時にテキストのプロンプトの値を読み込むことで、各セクションが展開なのか省略なのかを判定することができます。
・ボタンを押したタイミングでdisplay変数を変更すると共に、テキストのプロンプトの値を更新しにいきます
・レポート再描画されるタイミングでプロンプト値が確定されるため、再描画実行後に取得する値は更新された値となり、展開/省略の状態を引き継いでHTML生成することが可能となります


#レポートxml
```xml:レポートxml
<report xmlns="http://developer.cognos.com/schemas/report/12.0/" useStyleVersion="10" expressionLocale="ja-jp">
				<modelPath>/content/folder[@name=&apos;サンプル_DQ&apos;]/folder[@name=&apos;モデル&apos;]/package[@name=&apos;GO データ ウェアハウス (クエリー)&apos;]/model[@name=&apos;model&apos;]</modelPath>
				<drillBehavior/>
				
				<layouts>
					<layout>
						<reportPages>
							<page name="ページ1"><style><defaultStyles><defaultStyle refStyle="pg"/></defaultStyles></style>
								<pageBody><style><defaultStyles><defaultStyle refStyle="pb"/></defaultStyles></style>
									<contents>
										
									<table><style><defaultStyles><defaultStyle refStyle="tb"/></defaultStyles><CSS value="border-collapse:collapse"/></style><tableRows><tableRow><tableCells><tableCell><contents><HTMLItem>
			<dataSource>
				<staticValue>&lt;script type=&quot;text/javascript&quot;&gt;
	
	//onClick関数の定義
	// OCはOpenCloseの略
	function OC_func(OCno){
		
		var fwOpen = getFormWarpRequest();

		//クリックされた対象のエリアの判定
		var OCarea = &quot;OC&quot; + OCno;
		//制御したエリアの総数
		var OCmax = 3;
		//現在のフラブ値を取得
		var nowOC = fwOpen._textEditBoxOpenClose.value
		var newOC = &quot;&quot;;

		if(document.getElementById(OCarea).style.display==&quot;none&quot;){
			//クリックされたエリアの表示スタイルを切り替え
			document.getElementById(OCarea).style.display=&quot;block&quot;;
			//クリックさらたエリアが対応する桁の数字のみ更新する
			newOC=nowOC.substr(0,OCno)+&quot;1&quot;+nowOC.substr(OCno+1,OCmax);
			//更新されたフラグの値でプロンプトの値を書き換える
			fwOpen._textEditBoxOpenClose.value=newOC;
		} else {
			document.getElementById(OCarea).style.display=&quot;none&quot;;
			newOC=nowOC.substr(0,OCno)+&quot;0&quot;+nowOC.substr(OCno+1,OCmax);
			fwOpen._textEditBoxOpenClose.value=newOC;
		}
	}
&lt;/script&gt;</staticValue>
			</dataSource>
		</HTMLItem></contents></tableCell><tableCell><contents/></tableCell><tableCell><contents><textItem><dataSource><reportExpression>ParamDisplayValue(&apos;pOC&apos;)</reportExpression></dataSource></textItem></contents></tableCell></tableCells></tableRow><tableRow><tableCells><tableCell><contents><textBox parameter="pOC" required="false" name="OpenClose"><defaultSelections><defaultSimpleSelection>000</defaultSimpleSelection></defaultSelections></textBox></contents></tableCell><tableCell><contents/></tableCell><tableCell><contents/></tableCell></tableCells></tableRow><tableRow><tableCells><tableCell><contents/></tableCell><tableCell><contents/></tableCell><tableCell><contents/></tableCell></tableCells></tableRow><tableRow><tableCells><tableCell><contents/></tableCell><tableCell><contents/></tableCell><tableCell><contents/></tableCell></tableCells></tableRow><tableRow><tableCells><tableCell><contents><HTMLItem>
			<dataSource>
				<staticValue>&lt;input type=&quot;button&quot; name=&quot;BTN1&quot; value=&quot;展開/省略&quot; onClick=&quot;OC_func(0)&quot;&gt;</staticValue>
			</dataSource>
		</HTMLItem></contents></tableCell><tableCell><contents><HTMLItem>
			<dataSource>
				<staticValue>&lt;div id=&quot;OC0&quot; style=&quot;display: block;&quot;&gt;</staticValue>
			</dataSource>
		</HTMLItem><selectWithSearch parameter="パラメーター1" refQuery="クエリー1" required="false"><useItem refDataItem="製品ライン コード"><displayItem refDataItem="製品ライン"/></useItem></selectWithSearch><HTMLItem>
			<dataSource>
				<staticValue>&lt;/div&gt;</staticValue>
			</dataSource>
		</HTMLItem></contents></tableCell><tableCell><contents/></tableCell></tableCells></tableRow><tableRow><tableCells><tableCell><contents><HTMLItem>
			<dataSource>
				<staticValue>&lt;input type=&quot;button&quot; name=&quot;BTN2&quot; value=&quot;展開/省略&quot; onClick=&quot;OC_func(1)&quot;&gt;</staticValue>
			</dataSource>
		</HTMLItem></contents></tableCell><tableCell><contents><HTMLItem>
			<dataSource>
				<staticValue>&lt;div id=&quot;OC1&quot; style=&quot;display: block;&quot;&gt;</staticValue>
			</dataSource>
		</HTMLItem><selectWithSearch parameter="パラメーター1" refQuery="クエリー1" required="false"><useItem refDataItem="製品ライン コード"><displayItem refDataItem="製品ライン"/></useItem></selectWithSearch><HTMLItem>
			<dataSource>
				<staticValue>&lt;/div&gt;</staticValue>
			</dataSource>
		</HTMLItem></contents></tableCell><tableCell><contents/></tableCell></tableCells></tableRow><tableRow><tableCells><tableCell><contents><HTMLItem>
			<dataSource>
				<staticValue>&lt;script&gt;
	//レポート実行時のHTML生成で展開と省略を制御する

	var fw = getFormWarpRequest();
	//制御したいエリアの総数。for文の最大値とする
	var OCmax = 3

	//プロンプトのデフォルト値を変数に格納
	var currentOC = fw._textEditBoxOpenClose.value
	
	for(var i = 0; i &lt; OCmax; i++) {
		var OCarea = &quot;OC&quot; + i;
		//対象のエリアに紐づく桁数のフラグを取得
		var myOC = currentOC.substr(i,1);

		if(myOC==0){
			//フラグが0なので、スタイルをnoneに設定
			document.getElementById(OCarea).style.display=&quot;none&quot;;
		} else {
			document.getElementById(OCarea).style.display=&quot;block&quot;;
		}
	}

&lt;/Script&gt;
</staticValue>
			</dataSource>
		</HTMLItem></contents></tableCell><tableCell><contents/></tableCell><tableCell><contents/></tableCell></tableCells></tableRow><tableRow><tableCells><tableCell><contents><promptButton type="next">
			<contents/>
			<style>
				<defaultStyles>
					<defaultStyle refStyle="bp"/>
				</defaultStyles>
			</style>
		</promptButton></contents></tableCell><tableCell><contents/></tableCell><tableCell><contents/></tableCell></tableCells></tableRow></tableRows></table></contents>
								</pageBody>
								<pageHeader>
									<contents>
										<block><style><defaultStyles><defaultStyle refStyle="ta"/></defaultStyles></style>
											<contents>
												<textItem><style><defaultStyles><defaultStyle refStyle="tt"/></defaultStyles></style>
													<dataSource>
														<staticValue/>
													</dataSource>
												</textItem>
											</contents>
										</block>
									</contents>
									<style>
										<defaultStyles>
											<defaultStyle refStyle="ph"/>
										</defaultStyles>
										<CSS value="padding-bottom:10px"/>
									</style>
								</pageHeader>
								<pageFooter>
									<contents>
										<table>
											<tableRows>
												<tableRow>
													<tableCells>
														<tableCell>
															<contents>
																<date>
																	<style>
																		<dataFormat>
																			<dateFormat/>
																		</dataFormat>
																	</style>
																</date>
															</contents>
															<style>
																<CSS value="vertical-align:top;text-align:left;width:25%"/>
															</style>
														</tableCell>
														<tableCell>
															<contents>
																<pageNumber/>
															</contents>
															<style>
																<CSS value="vertical-align:top;text-align:center;width:50%"/>
															</style>
														</tableCell>
														<tableCell>
															<contents>
																<time>
																	<style>
																		<dataFormat>
																			<timeFormat/>
																		</dataFormat>
																	</style>
																</time>
															</contents>
															<style>
																<CSS value="vertical-align:top;text-align:right;width:25%"/>
															</style>
														</tableCell>
													</tableCells>
												</tableRow>
											</tableRows>
											<style>
												<defaultStyles>
													<defaultStyle refStyle="tb"/>
												</defaultStyles>
												<CSS value="border-collapse:collapse;width:100%"/>
											</style>
										</table>
									</contents>
									<style>
										<defaultStyles>
											<defaultStyle refStyle="pf"/>
										</defaultStyles>
										<CSS value="padding-top:10px"/>
									</style>
								</pageFooter>
							</page>
						</reportPages>
					<promptPages><page name="プロンプト・ページ1">
			<pageHeader>
				<contents>
					<block>
						<contents>
							<textItem>
								<dataSource>
									<staticValue/>
								</dataSource>
								<style>
									<defaultStyles>
										<defaultStyle refStyle="tt"/>
									</defaultStyles>
								</style>
							</textItem>
						</contents>
						<style>
							<defaultStyles>
								<defaultStyle refStyle="ta"/>
							</defaultStyles>
						</style>
					</block>
				</contents>
				<style>
					<defaultStyles>
						<defaultStyle refStyle="hp"/>
					</defaultStyles>
				</style>
			</pageHeader>
			<pageBody>
				<contents><table><style><defaultStyles><defaultStyle refStyle="tb"/></defaultStyles><CSS value="border-collapse:collapse"/></style><tableRows><tableRow><tableCells><tableCell><contents><HTMLItem>
			<dataSource>
				<staticValue>&lt;script type=&quot;text/javascript&quot;&gt;
	
	//onClick関数の定義
	// OCはOpenCloseの略
	function OC_func(OCno){
		
		var fwOpen = getFormWarpRequest();

		//クリックされた対象のエリアの判定
		var OCarea = &quot;OC&quot; + OCno;
		//制御したエリアの総数
		var OCmax = 3;
		//現在のフラブ値を取得
		var nowOC = fwOpen._textEditBoxOpenClose1.value
		var newOC = &quot;&quot;;

		if(document.getElementById(OCarea).style.display==&quot;none&quot;){
			//クリックされたエリアの表示スタイルを切り替え
			document.getElementById(OCarea).style.display=&quot;block&quot;;
			//クリックさらたエリアが対応する桁の数字のみ更新する
			newOC=nowOC.substr(0,OCno)+&quot;1&quot;+nowOC.substr(OCno+1,OCmax);
			//更新されたフラグの値でプロンプトの値を書き換える
			fwOpen._textEditBoxOpenClose1.value=newOC;
		} else {
			document.getElementById(OCarea).style.display=&quot;none&quot;;
			newOC=nowOC.substr(0,OCno)+&quot;0&quot;+nowOC.substr(OCno+1,OCmax);
			fwOpen._textEditBoxOpenClose1.value=newOC;
		}
	}
&lt;/script&gt;</staticValue>
			</dataSource>
		</HTMLItem></contents></tableCell><tableCell><contents/></tableCell><tableCell><contents><textItem><dataSource><reportExpression>ParamDisplayValue(&apos;pOC&apos;)</reportExpression></dataSource></textItem></contents></tableCell></tableCells></tableRow><tableRow><tableCells><tableCell><contents><textBox parameter="pOC" required="false" name="OpenClose1"><defaultSelections><defaultSimpleSelection>000</defaultSimpleSelection></defaultSelections></textBox></contents></tableCell><tableCell><contents/></tableCell><tableCell><contents/></tableCell></tableCells></tableRow><tableRow><tableCells><tableCell><contents/></tableCell><tableCell><contents/></tableCell><tableCell><contents/></tableCell></tableCells></tableRow><tableRow><tableCells><tableCell><contents/></tableCell><tableCell><contents/></tableCell><tableCell><contents/></tableCell></tableCells></tableRow><tableRow><tableCells><tableCell><contents><HTMLItem>
			<dataSource>
				<staticValue>&lt;input type=&quot;button&quot; name=&quot;BTN1&quot; value=&quot;展開/省略&quot; onClick=&quot;OC_func(0)&quot;&gt;</staticValue>
			</dataSource>
		</HTMLItem></contents></tableCell><tableCell><contents><HTMLItem>
			<dataSource>
				<staticValue>&lt;div id=&quot;OC0&quot; style=&quot;display: block;&quot;&gt;</staticValue>
			</dataSource>
		</HTMLItem><selectWithSearch parameter="パラメーター1" refQuery="クエリー1" required="false"><useItem refDataItem="製品ライン コード"><displayItem refDataItem="製品ライン"/></useItem></selectWithSearch><HTMLItem>
			<dataSource>
				<staticValue>&lt;/div&gt;</staticValue>
			</dataSource>
		</HTMLItem></contents></tableCell><tableCell><contents/></tableCell></tableCells></tableRow><tableRow><tableCells><tableCell><contents><HTMLItem>
			<dataSource>
				<staticValue>&lt;input type=&quot;button&quot; name=&quot;BTN2&quot; value=&quot;展開/省略&quot; onClick=&quot;OC_func(1)&quot;&gt;</staticValue>
			</dataSource>
		</HTMLItem></contents></tableCell><tableCell><contents><HTMLItem>
			<dataSource>
				<staticValue>&lt;div id=&quot;OC1&quot; style=&quot;display: block;&quot;&gt;</staticValue>
			</dataSource>
		</HTMLItem><selectWithSearch parameter="パラメーター1" refQuery="クエリー1" required="false"><useItem refDataItem="製品ライン コード"><displayItem refDataItem="製品ライン"/></useItem></selectWithSearch><HTMLItem>
			<dataSource>
				<staticValue>&lt;/div&gt;</staticValue>
			</dataSource>
		</HTMLItem></contents></tableCell><tableCell><contents/></tableCell></tableCells></tableRow><tableRow><tableCells><tableCell><contents><HTMLItem>
			<dataSource>
				<staticValue>&lt;script&gt;
	//レポート実行時のHTML生成で展開と省略を制御する

	var fw = getFormWarpRequest();
	//制御したいエリアの総数。for文の最大値とする
	var OCmax = 3

	//プロンプトのデフォルト値を変数に格納
	var currentOC = fw._textEditBoxOpenClose1.value
	
	for(var i = 0; i &lt; OCmax; i++) {
		var OCarea = &quot;OC&quot; + i;
		//対象のエリアに紐づく桁数のフラグを取得
		var myOC = currentOC.substr(i,1);

		if(myOC==0){
			//フラグが0なので、スタイルをnoneに設定
			document.getElementById(OCarea).style.display=&quot;none&quot;;
		} else {
			document.getElementById(OCarea).style.display=&quot;block&quot;;
		}
	}
&lt;/Script&gt;
</staticValue>
			</dataSource>
		</HTMLItem></contents></tableCell><tableCell><contents/></tableCell><tableCell><contents/></tableCell></tableCells></tableRow><tableRow><tableCells><tableCell><contents><promptButton type="next">
			<contents/>
			<style>
				<defaultStyles>
					<defaultStyle refStyle="bp"/>
				</defaultStyles>
			</style>
		</promptButton></contents></tableCell><tableCell><contents/></tableCell><tableCell><contents/></tableCell></tableCells></tableRow></tableRows></table></contents>
				<style>
					<defaultStyles>
						<defaultStyle refStyle="py"/>
					</defaultStyles>
				</style>
			</pageBody>
			<pageFooter>
				<contents>
					<promptButton type="cancel">
						<contents/>
						<style>
							<defaultStyles>
								<defaultStyle refStyle="bp"/>
							</defaultStyles>
						</style>
					</promptButton>
					<promptButton type="back">
						<contents/>
						<style>
							<defaultStyles>
								<defaultStyle refStyle="bp"/>
							</defaultStyles>
						</style>
					</promptButton>
					<promptButton type="next">
						<contents/>
						<style>
							<defaultStyles>
								<defaultStyle refStyle="bp"/>
							</defaultStyles>
						</style>
					</promptButton>
					<promptButton type="finish">
						<contents/>
						<style>
							<defaultStyles>
								<defaultStyle refStyle="bp"/>
							</defaultStyles>
						</style>
					</promptButton>
				</contents>
				<style>
					<defaultStyles>
						<defaultStyle refStyle="fp"/>
					</defaultStyles>
				</style>
			</pageFooter>
			<style>
				<defaultStyles>
					<defaultStyle refStyle="pp"/>
				</defaultStyles>
			</style>
		</page></promptPages></layout>
				</layouts>
			<XMLAttributes><XMLAttribute name="RS_CreateExtendedDataItems" value="true" output="no"/><XMLAttribute name="listSeparator" value="," output="no"/><XMLAttribute name="RS_modelModificationTime" value="2013-02-11T15:27:07.760Z" output="no"/></XMLAttributes><reportName>パカパカサンプル_02</reportName><queries><query name="クエリー1"><source><model/></source><selection><dataItem name="製品ライン コード" aggregate="none"><expression>[販売 (クエリー)].[製品].[製品ライン コード]</expression></dataItem><dataItem name="製品ライン" aggregate="none" sort="ascending"><expression>[販売 (クエリー)].[製品].[製品ライン]</expression></dataItem></selection></query></queries></report>
```
#応用
同じセクションを使用しているレポート間において、ドリルスルーのパラメータとしてテキストのプロンプトの値を引き継げば、ドリルスルー先で展開/省略の状態を覚えてレポートを実行することが可能になります。

#最後に
当サンプルレポートはCognos BI 10.2.2を使用して作成しています。
Cognos Analytics 11.0.6、11.0.9でも稼動することは確認していますが、xmlをコピーして移行する場合は、Cognos Anakytics側で最初に「完全な双方向性」の設定を「いいえ」に設定するようにしてください。