WINDOW
構文
引数
説明
window_function
(必須) Window関数
[partitionby_function]
(オプション) 行をパーティションに分割する
[orderby_function]
(オプション) 各パーティションにある行の並び替えを定義する
[frame_function]
(オプション) パーティションのwindow frameを構成する行の集合の開始点と終了点を指定する。
注意事項
WINDOWはWINDOW関数でのみ使用できます。行全体をひとつのwindowとして扱い、PARTITIONBY、ORDERBYの設定によって行の順序が変わります。
PARTITIONBY
構文
引数
説明
field_function
(必須) パーティションのフィールド名または数式
注意事項
PARTITIONBY は行をパーティションに分割し、各パーティションにwindow関数を適用します。1つ以上の引数を設定する必要があります。
例:
ORDERBY
構文
引数
説明
field_function
(必須) ソートするフィールド名または数式
引数
説明
field_function
(必須) ソートするフィールド名または数式
注意事項
ORDERBYは、各パーティション内の行のソート順を定義します。指定したwindowおよびWINDOW関数の計算に影響します。また、1つ以上の引数を設定する必要があり、ORDERASCとORDERDESCを使用して、ソート順を昇順または降順に設定することができます。デフォルト値は昇順 ORDERASCです。
例:
FRAMEROWS
構文
引数
説明
beginning_function
(必須) 現在行の前にある行数
[ending_function]
(オプション) 現在行の後にある行数
[exclude_mode]
(オプション) 特定の行を除外するモードを指定する:0 - 除外部分がない1 - 現在行は除外する。ただし、FRAMEGROUPSとFRAMERANGEの場合はその対等行を除外しない。2 - 現在行とその対等行を除外する。3 - 現在行を除外しないが、その対等行を除外する。
注意事項
FRAMEROWSは、現在行の前後にある行数を指定することによって、windowの行セットを制限します。第1引数は現在行の前にある行数、第2引数は現在行の後にある行数を示します。いずれも-1、[@-n]、または[@]を指定できます。-1は現在のパーティションの境界、-nは行数、[@]は現在行を示します。例:
FRAMERANGE
構文
引数
説明
beginning_function
(必須) 現在行の前にある距離
[ending_function]
(オプション) 現在行の後にある距離
[exclude_mode]
(オプション) 特定の行を除外するモードを指定する。FRAMEROWSの引数と同様
注意事項
FRAMERANGEは、現在行の前後にある距離を指定することによって、windowの範囲を制限します。この距離は現在行まで同じ値を持つ行で、ORDERBYに設定した列によって構成されます。
第1引数は現在行の前にある距離を示し、-1、[@-n](降順の場合は[@+n])、または[@]を指定できます。第2引数は現在行の後にある距離を示し、-1、[@+n](降順の場合は[@-n])、または[@]を指定できます。-1は現在のパーティションの境界、-nは距離、[@]は同じ値を持つ並列行を示します。この範囲は閉区間であり、最初の列に数値型でORDERBYに設定する必要があります。例:
FRAMEGROUPS
構文
引数
説明
beginning_function
(必須) 現在のグループより前のグループ数
[ending_function]
(オプション) 現在のグループの後のグループ数
[exclude_mode]
(オプション) 特定の行を除外するモードを指定する。FRAMEROWSの引数と同様
注意事項
FRAMEGROUPSは、現在のグループの前後にあるグループ数を指定することによって、windowの範囲を制限します。このグループ数は現在のグループまで同じ値を持つ行で、ORDERBYに設定した列によって構成されます。
第1引数は現在のグループの前にあるグループ数を示し、-1、[@-n](降順の場合は[@+n])、または[@]を指定できます。第2引数は現在のグループの後にあるグループ数を示し、-1、[@+n]、[@-n]、または[@]を指定できます。-1は現在のパーティションの境界(開始または終了)、[@-n]または[@+n]は現在のグループの前後にあるグループ数、nはグループ数、[@]は現在のグループを示します。例:
Window Chaining
構文
注意事項
Window chainingは、ひとつのウィンドウを事前に定義し、新しいウィンドウに再利用する場合にPARTITYIONBYやORDERBY、またはWindow Frameを再利用できるようにする省略記法です。
事前に定義されたWINDOW関数を新しいウィンドウに適用する際に、PARTITIONBY,FRAME,ORDERBYを再利用/上書きすることができます。WINDOWDEFを使用してウィンドウを事前に定義します:
/*REPLACE_MARKER*/
/*DO NOT DELETE THESE COMMENTS*/
window.onload = function () {
var spread = new GC.Spread.Sheets.Workbook(document.getElementById("ss"), { sheetCount: 0 });
initSpread(spread);
};
function initSpread(spread) {
spread.suspendPaint();
spread.clearSheets();
spread.options.autoFitType = GC.Spread.Sheets.AutoFitType.cellWithHeader;
spread.options.allowDynamicArray = true;
spread.options.highlightInvalidData = true;
spread.options.calcOnDemand = true;
discountAmount(spread);
revenueTrends(spread);
quantityRevenueTrends(spread);
monthlyRevenueTrends(spread);
spread.resumePaint();
}
function discountAmount(spread) {
//init a data manager
var dataManager = spread.dataManager();
var discountAmountTable = dataManager.addTable("discountAmountTable", {
remote: {
read: {
url: "$DEMOROOT$/spread/source/data/orderPriceQuantityData.csv"
}
},
schema: {
type: "csv",
columns: {
OrderDate: { dataType: "date" },
Quantity: { dataType: "number" },
Price: { dataType: "number" },
Amount: { dataType: 'formula', value: "=[@Price] * [@Quantity]" },
DiscountAmount: { dataType: 'formula', value: "=IF([@Quantity] > 30, [@Amount] * 0.8, [@Amount])" },
},
window: {
BeginCurrent: '=WINDOWDEF(PARTITIONBY([Category], [Product], YEAR([@OrderDate])), FRAMEROWS(-1,[@]))',
BeginEnd: '=WINDOWDEF(PARTITIONBY([Category], [Product], YEAR([@OrderDate])))',
}
}
});
//init a table sheet
var sheet = spread.addSheetTab(0, "Discount Amount", GC.Spread.Sheets.SheetType.tableSheet);
sheet.setDefaultRowHeight(40, GC.Spread.Sheets.SheetArea.colHeader);
sheet.options.allowAddNew = false; //hide new row
//bind a view to the table sheet
discountAmountTable.fetch().then(function () {
var discountHighlightRule = {
ruleType: "formulaRule",
formula: "[@Quantity]>30",
style: {
foreColor: "purple"
}
};
var myView = discountAmountTable.addView("myView", [
{ value: "Category", width: 90 },
{ value: "Product", width: 90 },
{ value: "=YEAR([@OrderDate])", caption: "Year", width: 80 },
{ value: "Amount", caption: "Amount", width: 100, conditionalFormats: [discountHighlightRule] },
// If the quantity exceeds 30, 20% off sales amount
{ value: "DiscountAmount", caption: "Discount Amount", conditionalFormats: [discountHighlightRule], width: 160 },
{ value: "Price", width: 70 },
{ value: "Quantity", width: 90, conditionalFormats: [discountHighlightRule] },
// The cumulative annual sales volume of each category and product
{ value: "=WINDOW(SUM([Quantity]), \"BeginCurrent\")", caption: 'Running Total Quantity', width: 190, style: { backColor: "#D9E1F2" } },
// The total annual sales volume of each category and product
{ value: "=WINDOW(SUM([Quantity]), \"BeginEnd\")", caption: 'Total Quantity', width: 140, style: { backColor: "#D9E1F2" } },
// The cumulative annual sales amount of each category and product, if the quantity exceeds 30, 20% off sales amount
{ value: "=WINDOW(SUM([DiscountAmount]), \"BeginCurrent\")", caption: 'Running Discount Total Amount', width: 240, style: { backColor: "#E2EFDA" } },
// The total annual sales amount of each category and product, if the quantity exceeds 30, 20% off sales amount
{ value: "=WINDOW(SUM([DiscountAmount]), \"BeginEnd\")", caption: 'Discount Total Amount', width: 190, style: { backColor: "#E2EFDA" } },
]);
spread.suspendPaint();
sheet.setDataView(myView);
spread.resumePaint();
});
}
function revenueTrends(spread) {
//init a data manager
var dataManager = spread.dataManager();
var revenueTrendsTable = dataManager.addTable("revenueTrendsTable", {
data: orderYearProductDataSource,
schema: {
type: "csv",
columns: {
Quantity: { dataType: "number" },
Amount: { dataType: "number" },
MovingAverageRevenue: { dataType: 'formula', value: '=WINDOW(AVERAGE([Amount]), "ProductYear")' },
},
window: {
ProductYear: '=WINDOWDEF(PARTITIONBY([Product]), ORDERBY([Year]), FRAMEROWS([@-2], [@]))'
}
}
});
//init a table sheet
var sheet = spread.addSheetTab(1, "Revenue Trends", GC.Spread.Sheets.SheetType.tableSheet);
sheet.setDefaultRowHeight(40, GC.Spread.Sheets.SheetArea.colHeader);
sheet.options.allowAddNew = false; //hide new row
//bind a view to the table sheet
revenueTrendsTable.fetch().then(function () {
var myView = revenueTrendsTable.addView("myView", [
{ value: "Year", width: 150 },
{ value: "Product", width: 105 },
{ value: "Amount", caption: "Revenue", width: 100, style: { formatter: "#,##0.00" } },
// Calculate the 3-year moving average of earned per product
// FRAMEROWS([@-2], [@]): the preceding two years and current
{ value: 'MovingAverageRevenue', caption: 'Moving Average Revenue', width: 200, style: { backColor: "#E2EFDA", formatter: "#,##0.00" } },
// To show a ratio of increase and decrease between the current and moving average amount
{ value: '=VARISPARKLINE(ROUND(([@Amount] - [@MovingAverageRevenue]) / [@Amount], 2),0,,,,0.2,TRUE)', caption: 'Revenue Trends %', width: 200, style: { backColor: "#E2EFDA" } },
]);
spread.suspendPaint();
sheet.setDataView(myView);
spread.resumePaint();
});
}
function quantityRevenueTrends(spread) {
//init a data manager
var dataManager = spread.dataManager();
var quantityRevenueTrendsTable = dataManager.addTable("quantityRevenueTrendsTable", {
remote: {
read: {
url: "$DEMOROOT$/spread/source/data/orderAmountData.csv"
}
},
schema: {
type: "csv",
columns: {
OrderDate: { dataType: "date" },
Amount: { dataType: "number" },
AverageRevenue: { dataType: 'formula', value: '=WINDOW(AVERAGE([Amount]), "ProductRangeAmount")' },
QuantityOfRevenue: { dataType: 'formula', value: '=WINDOW(COUNT([Amount]), "ProductRangeAmount")' },
},
window: {
ProductRangeAmount: '=WINDOWDEF(PARTITIONBY([Product]), ORDERBY([Amount]), FRAMERANGE([@-200], [@+200]))'
}
}
});
//init a table sheet
var sheet = spread.addSheetTab(2, "Quantity Of Revenue Trends", GC.Spread.Sheets.SheetType.tableSheet);
sheet.setDefaultRowHeight(40, GC.Spread.Sheets.SheetArea.colHeader);
sheet.options.allowAddNew = false; //hide new row
//bind a view to the table sheet
quantityRevenueTrendsTable.fetch().then(function () {
var myView = quantityRevenueTrendsTable.addView("myView", [
{ value: "Product", width: 150 },
{ value: "Amount", caption: "Revenue", width: 100, style: { formatter: "#,##0.00" } },
// The trend comparison of average selling prices and the quantity of the proximate orders
// When the price is within a certain range, there are more orders
// When the price is higher or lower, the order quantity decreases
// This situation of the quantity of the orders are close to the normal distribution
// The analytic function AVERAGE can obtain the average of proximate selling prices within each product
// FRAMERANGE([@-200], [@+200]): the amount range which minus or plus 200 against current amount will help to retrieve the orders as a window
{ value: "AverageRevenue", caption: 'Average Revenue', width: 150, style: { backColor: "#E2EFDA", formatter: "#,##0.00" } },
// Calculating the ratio of the average amount of the proximate orders against max amount in each product to show the bars
{ value: "=HBARSPARKLINE([@AverageRevenue] / WINDOW(MAX([Amount]), PARTITIONBY([Product])), \"#347B98\")", caption: 'Average Revenue Trends', width: 200, style: { backColor: "#E2EFDA" } },
// The analytic function COUNT can obtain the quantity of proximate selling prices within each product
// FRAMERANGE([@-200], [@+200]): the amount range which minus or plus 200 against current amount will help to retrieve the orders as a window
{ value: "QuantityOfRevenue", caption: 'Quantity Of Revenue', width: 180, style: { backColor: "#E2EFDA" } },
// Using LET to cached the ratio of the number of the proximate orders against the total number of the orders in each product to show the bars which indicates the trends through the ratio and colors
{ value: "=LET(ratio, [@QuantityOfRevenue] / WINDOW(COUNT([Amount]), PARTITIONBY([Product])),color,IF(ratio >= 0.32,\"green\", IF(ratio >= 0.2, \"#66B032\", IF(ratio >= 0.1, \"#B2D732\", \"red\"))), HBARSPARKLINE(ratio, color))", caption: 'Quantity Of Revenue Trends', width: 200, style: { backColor: "#E2EFDA" } },
]);
spread.suspendPaint();
sheet.setDataView(myView);
spread.resumePaint();
});
}
function monthlyRevenueTrends(spread) {
//init a data manager
var dataManager = spread.dataManager();
var monthlyRevenueTrendsTable = dataManager.addTable("monthlyRevenueTrendsTable", {
remote: {
read: {
url: "$DEMOROOT$/spread/source/data/orderAmountData.csv"
}
},
schema: {
type: "csv",
columns: {
OrderDate: { dataType: "date" },
Amount: { dataType: "number" },
MonthlyAverageRevenue: { dataType: 'formula', value: '=WINDOW(AVERAGE([Amount]), "ProductMonthly")' },
NearlyAverageRevenue: { dataType: 'formula', value: '=WINDOW(AVERAGE([Amount]), "ProductMonthly", FRAMEGROUPS([@-2], [@+2], 2))' },
},
window: {
ProductMonthly: '=WINDOWDEF(PARTITIONBY([Product]), ORDERBY(VALUE(DATEPART([@OrderDate], "M"))), FRAMEGROUPS([@], [@]))'
}
}
});
//init a table sheet
var sheet = spread.addSheetTab(3, "Monthly Revenue Trends", GC.Spread.Sheets.SheetType.tableSheet);
sheet.setDefaultRowHeight(40, GC.Spread.Sheets.SheetArea.colHeader);
sheet.options.allowAddNew = false; //hide new row
//bind a view to the table sheet
monthlyRevenueTrendsTable.fetch().then(function () {
var myView = monthlyRevenueTrendsTable.addView("myView", [
{ value: "Product", width: 150 },
{ value: '=VALUE(DATEPART([@OrderDate], "M"))', caption: 'Month', width: 150 },
{ value: "Amount", caption: "Revenue", width: 100, style: { formatter: "#,##0.00" } },
// Compare the monthly and nearly average of earned per product
// Current month average revenue
{ value: 'MonthlyAverageRevenue', caption: 'Monthly Average Revenue', width: 220, style: { backColor: "#E2EFDA", formatter: "#,##0.00" } },
// The nearly average revenue without the current month
// For FRAMEGROUPS, [@-2] indicates two months before current, [@+2] indicates two months after current, and the exclude mode is 2 that indicates the current row and the peers are all excluded.
{ value: 'NearlyAverageRevenue', caption: 'Nearly Average Revenue', width: 200, style: { backColor: "#E2EFDA", formatter: "#,##0.00" } },
// To show a ratio of increase and decrease between the current and nearly average amount
{ value: '=VARISPARKLINE(ROUND(([@MonthlyAverageRevenue] - [@NearlyAverageRevenue]) / [@MonthlyAverageRevenue], 2),0,,,,0.2,TRUE)', caption: 'Revenue Trends %', width: 200, style: { backColor: "#E2EFDA" } },
]);
spread.suspendPaint();
sheet.setDataView(myView);
spread.resumePaint();
});
}
<!doctype html>
<html style="height:100%;font-size:14px;">
<head>
<meta charset="utf-8" />
<meta name="spreadjs culture" content="ja-jp" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" type="text/css" href="$DEMOROOT$/ja/purejs/node_modules/@mescius/spread-sheets/styles/gc.spread.sheets.excel2013white.css">
<!-- Promise Polyfill for IE, https://www.npmjs.com/package/promise-polyfill -->
<script src="https://cdn.jsdelivr.net/npm/promise-polyfill@8/dist/polyfill.min.js"></script>
<script src="$DEMOROOT$/ja/purejs/node_modules/@mescius/spread-sheets/dist/gc.spread.sheets.all.min.js" type="text/javascript"></script>
<script src="$DEMOROOT$/ja/purejs/node_modules/@mescius/spread-sheets-tablesheet/dist/gc.spread.sheets.tablesheet.min.js" type="text/javascript"></script>
<script src="$DEMOROOT$/spread/source/data/orderDataSource.js" type="text/javascript"></script>
<script src="$DEMOROOT$/spread/source/data/orderYearProductDataSource.js" type="text/javascript"></script>
<script src="$DEMOROOT$/ja/purejs/node_modules/@mescius/spread-sheets-resources-ja/dist/gc.spread.sheets.resources.ja.min.js" type="text/javascript"></script>
<script src="$DEMOROOT$/spread/source/js/license.js" type="text/javascript"></script>
<script src="app.js" type="text/javascript"></script>
<link rel="stylesheet" type="text/css" href="styles.css">
</head>
<body>
<div class="sample-tutorial">
<div id="ss" class="sample-spreadsheets"></div>
</div>
</html>
.sample-tutorial {
position: relative;
height: 100%;
overflow: hidden;
}
.sample-spreadsheets {
width: 100%;
height: 100%;
overflow: hidden;
float: left;
}
.options-container {
float: right;
width: 210px;
padding: 12px;
height: 100%;
box-sizing: border-box;
background: #fbfbfb;
overflow: auto;
}
.option-row {
font-size: 14px;
padding: 5px;
margin-top: 10px;
}
label {
display: block;
margin-bottom: 3px;
margin-top: 3px;
}
input {
padding: 4px 6px;
}
input[type=button] {
margin-top: 6px;
display: block;
width: 100%;
text-align: center;
}
input[type=text] {
width: 230px;
}
body {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
margin: 0;
}