正しくないフォーマットの日付を検証できない場合がある
対象製品
SpreadJS 9J
発生環境
SP1(9.20161.0), FireFox, Internet Explorer
詳細
日付データの"月"や"日"に該当する部分に最終月、最終日を上回る(もしくは下回る)数字を設定した場合に、これを正しく検証できない現象が発生します。
【現象再現コード】
----------------------------------------
var condition = GC.Spread.Sheets.ConditionalFormatting.ComparisonOperators.between;
var startDate = new Date(2016, 0, 1);
var endDate = Date(2016, 11, 31);
var validator = GC.Spread.Sheets.DataValidation.createDateValidator(condition, startDate, endDate);
----------------------------------------
上記のような検証設定(日付有効範囲:2016/1/1 - 2016/12/31)を行ったセルで、以下のようなデータが正しく検証されません。(不正なデータとならず、正常なデータと判断されます。)
【正しく検証できない日付の例】
・2016/0/32
・2016/0/397
・2016/13/0
・2016/1/32
本現象は、Internet ExplorerおよびFireFoxにおけるJavaScriptの標準処理が、上記【正しく検証できない日付の例】を正しい日付として処理する動作に起因しており、製品の内部動作からこれを制御し、"正しくない日付"として扱うことができません。
【現象再現コード】
----------------------------------------
var condition = GC.Spread.Sheets.ConditionalFormatting.ComparisonOperators.between;
var startDate = new Date(2016, 0, 1);
var endDate = Date(2016, 11, 31);
var validator = GC.Spread.Sheets.DataValidation.createDateValidator(condition, startDate, endDate);
----------------------------------------
上記のような検証設定(日付有効範囲:2016/1/1 - 2016/12/31)を行ったセルで、以下のようなデータが正しく検証されません。(不正なデータとならず、正常なデータと判断されます。)
【正しく検証できない日付の例】
・2016/0/32
・2016/0/397
・2016/13/0
・2016/1/32
本現象は、Internet ExplorerおよびFireFoxにおけるJavaScriptの標準処理が、上記【正しく検証できない日付の例】を正しい日付として処理する動作に起因しており、製品の内部動作からこれを制御し、"正しくない日付"として扱うことができません。
回避方法
下記のようなカスタム検証を作成することで、現象の回避が可能です。
----------------------------------------
window.onload = function(){
// 初期化処理
var spread = new GC.Spread.Sheets.Workbook(document.getElementById("ss"));
var sheet = spread.getActiveSheet();
// 検証の設定
var startDate = new Date(2016, 0, 1);
var endDate = new Date(2016, 11, 31);
var validator = new GC.Spread.Sheets.DataValidation.DefaultDataValidator(new CustomDateCondition(startDate, endDate));
validator.type(GC.Spread.Sheets.DataValidation.CriteriaType.custom);
sheet.getCell(3, 3).backColor('yellow').validator(validator);
// 検証エラー発生時の処理
sheet.bind(GC.Spread.Sheets.Events.ValidationError, function (sendar, args) {
args.validationResult = GC.Spread.Sheets.DataValidation.DataValidationResult.discard;
setTimeout(function () {
alert("無効なデータです");
}, 0);
})
}
//--------------------------------------------------
// カスタム検証処理【回避コード】
//--------------------------------------------------
function CustomDateCondition(date1, date2) {
var con1 = new
GC.Spread.Sheets.ConditionalFormatting.Condition(GC.Spread.Sheets.ConditionalFormatting.ConditionType.dateCondition, {
compareType: GC.Spread.Sheets.ConditionalFormatting.DateCompareType.afterEqualsTo,
expected: date1
});
var con2 = new
GC.Spread.Sheets.ConditionalFormatting.Condition(GC.Spread.Sheets.ConditionalFormatting.ConditionType.dateCondition, {
compareType: GC.Spread.Sheets.ConditionalFormatting.DateCompareType.beforeEqualsTo,
expected: date2
});
GC.Spread.Sheets.ConditionalFormatting.Condition.call(this, GC.Spread.Sheets.ConditionalFormatting.ConditionType.relationCondition,
{compareType: GC.Spread.Sheets.ConditionalFormatting.LogicalOperators.and, item1: con1, item2: con2});
}
CustomDateCondition.prototype = new GC.Spread.Sheets.ConditionalFormatting.Condition();
CustomDateCondition.prototype.evaluate = function (evaluator, baseRow, baseColumn, actualObj) {
if(actualObj){
if(this._isValidDateString(actualObj)){
return GC.Spread.Sheets.ConditionalFormatting.Condition.prototype.evaluate.apply(this, arguments);
}
return false;
}
return false;
}
CustomDateCondition.prototype._isValidDateString = function (dateObj) {
if(typeof(dateObj)==="string"){
//"yyyy/mm/dd", "yyy-mm-dd", "dd/mm/yyyy"を検証する処理
var arr = dateObj.split("/");
if (arr.length !== 3) {
return false;
}
var year = +arr[0], month = +arr[1], day = +arr[2];
var date = new Date(dateObj);
if (date.getFullYear() === year &&
date.getMonth() === month - 1 &&
date.getDate() === day) {
return true;
}
return false;
}
return true;
}
----------------------------------------
----------------------------------------
window.onload = function(){
// 初期化処理
var spread = new GC.Spread.Sheets.Workbook(document.getElementById("ss"));
var sheet = spread.getActiveSheet();
// 検証の設定
var startDate = new Date(2016, 0, 1);
var endDate = new Date(2016, 11, 31);
var validator = new GC.Spread.Sheets.DataValidation.DefaultDataValidator(new CustomDateCondition(startDate, endDate));
validator.type(GC.Spread.Sheets.DataValidation.CriteriaType.custom);
sheet.getCell(3, 3).backColor('yellow').validator(validator);
// 検証エラー発生時の処理
sheet.bind(GC.Spread.Sheets.Events.ValidationError, function (sendar, args) {
args.validationResult = GC.Spread.Sheets.DataValidation.DataValidationResult.discard;
setTimeout(function () {
alert("無効なデータです");
}, 0);
})
}
//--------------------------------------------------
// カスタム検証処理【回避コード】
//--------------------------------------------------
function CustomDateCondition(date1, date2) {
var con1 = new
GC.Spread.Sheets.ConditionalFormatting.Condition(GC.Spread.Sheets.ConditionalFormatting.ConditionType.dateCondition, {
compareType: GC.Spread.Sheets.ConditionalFormatting.DateCompareType.afterEqualsTo,
expected: date1
});
var con2 = new
GC.Spread.Sheets.ConditionalFormatting.Condition(GC.Spread.Sheets.ConditionalFormatting.ConditionType.dateCondition, {
compareType: GC.Spread.Sheets.ConditionalFormatting.DateCompareType.beforeEqualsTo,
expected: date2
});
GC.Spread.Sheets.ConditionalFormatting.Condition.call(this, GC.Spread.Sheets.ConditionalFormatting.ConditionType.relationCondition,
{compareType: GC.Spread.Sheets.ConditionalFormatting.LogicalOperators.and, item1: con1, item2: con2});
}
CustomDateCondition.prototype = new GC.Spread.Sheets.ConditionalFormatting.Condition();
CustomDateCondition.prototype.evaluate = function (evaluator, baseRow, baseColumn, actualObj) {
if(actualObj){
if(this._isValidDateString(actualObj)){
return GC.Spread.Sheets.ConditionalFormatting.Condition.prototype.evaluate.apply(this, arguments);
}
return false;
}
return false;
}
CustomDateCondition.prototype._isValidDateString = function (dateObj) {
if(typeof(dateObj)==="string"){
//"yyyy/mm/dd", "yyy-mm-dd", "dd/mm/yyyy"を検証する処理
var arr = dateObj.split("/");
if (arr.length !== 3) {
return false;
}
var year = +arr[0], month = +arr[1], day = +arr[2];
var date = new Date(dateObj);
if (date.getFullYear() === year &&
date.getMonth() === month - 1 &&
date.getDate() === day) {
return true;
}
return false;
}
return true;
}
----------------------------------------