diff --git a/common/NumFormat.js b/common/NumFormat.js index 06f13ce7f3..9f0f494152 100644 --- a/common/NumFormat.js +++ b/common/NumFormat.js @@ -1306,16 +1306,23 @@ NumFormat.prototype = { //Разрешаем конфликты numFormat_MonthMinute var bRightCond = false; - //ищем вперед первый элемент с типом datetime - for(var j = i + 1; j < nFormatLength; ++j) + if (item.bElapsed) { - var subItem = this.aRawFormat[j]; - if(numFormat_Year == subItem.type || numFormat_Month == subItem.type || numFormat_Day == subItem.type || numFormat_MonthMinute == subItem.type || - numFormat_Hour == subItem.type || numFormat_Minute == subItem.type || numFormat_Second == subItem.type || numFormat_Milliseconds == subItem.type) + bRightCond = true; + } + else + { + //ищем вперед первый элемент с типом datetime + for(var j = i + 1; j < nFormatLength; ++j) { - if(numFormat_Second == subItem.type) - bRightCond = true; - break; + var subItem = this.aRawFormat[j]; + if(numFormat_Year == subItem.type || numFormat_Month == subItem.type || numFormat_Day == subItem.type || numFormat_MonthMinute == subItem.type || + numFormat_Hour == subItem.type || numFormat_Minute == subItem.type || numFormat_Second == subItem.type || numFormat_Milliseconds == subItem.type) + { + if(numFormat_Second == subItem.type) + bRightCond = true; + break; + } } } var bLeftCond = false; @@ -2727,13 +2734,25 @@ NumFormat.prototype = } else if(numFormat_Minute == item.type) { + if (item.bElapsed) { + res += "["; + } for(var j = 0; j < item.val; ++j) res += minute; + if (item.bElapsed) { + res += "]"; + } } else if(numFormat_Second == item.type) { + if (item.bElapsed) { + res += "["; + } for(var j = 0; j < item.val; ++j) res += second; + if (item.bElapsed) { + res += "]"; + } } else if(numFormat_DayOfWeek == item.type) { diff --git a/tests/cell/spreadsheet-calculation/NumFormatParse.html b/tests/cell/spreadsheet-calculation/NumFormatParse.html index af18fcdff2..cd6bdcbeb0 100644 --- a/tests/cell/spreadsheet-calculation/NumFormatParse.html +++ b/tests/cell/spreadsheet-calculation/NumFormatParse.html @@ -10,8 +10,12 @@ - - + + diff --git a/tests/cell/spreadsheet-calculation/NumFormatParse.js b/tests/cell/spreadsheet-calculation/NumFormatParse.js index 6524fa1e96..e7f93f1021 100644 --- a/tests/cell/spreadsheet-calculation/NumFormatParse.js +++ b/tests/cell/spreadsheet-calculation/NumFormatParse.js @@ -31,6 +31,12 @@ */ $(function () { + window["AscCommonExcel"] = window["AscCommonExcel"] || {}; + window["AscCommonExcel"].Font = function () { + }; + window["AscCommonExcel"].RgbColor = function () { + }; + QUnit.module('NumFomat parse'); let eps = 1e-15; QUnit.test('parseDate', function (assert) { @@ -83,4 +89,125 @@ $(function () { assert.strictEqual(Math.abs(date.value - data[i][2]) < eps, true, `Case value: ${data[i][0]}`); } }); + + QUnit.test('formatNumber', function (assert) { + let testCases = [ + // Thousand separators + [1234, '#,##0', '1,234'], + [1234567, '#,##0', '1,234,567'], + [0, '#,##0', '0'], + [-1234, '#,##0', '-1,234'], + + // Decimal places + [1234.56, '#,##0.00', '1,234.56'], + [1234.5, '#,##0.00', '1,234.50'], + [0.5, '0.00', '0.50'], + [1.234, '0.00', '1.23'], + + // Percentages + [0.5, '0%', '50%'], + [0.125, '0.00%', '12.50%'], + [1, '0%', '100%'], + [0.999, '0%', '100%'], + + // Currency with text literals + [1234.56, '"$"#,##0.00', '$1,234.56'], + [0, '"$"#,##0.00', '$0.00'], + [-50, '"$"#,##0.00', '-$50.00'], + [1000, '"USD "0.00', 'USD 1000.00'], + + // Negative numbers in parentheses + [100, '0;(0)', '100'], + [-100, '0;(0)', '(100)'], + [0, '0;(0)', '0'], + [-50.5, '0.00;(0.00)', '(50.50)'], + + // Optional digits with # + [123, '###', '123'], + [0, '###', ''], + [12.3, '##.#', '12.3'], + [12, '##.#', '12.'], + + // Mandatory zeros + [5, '000', '005'], + [123, '000', '123'], + [5.5, '000.00', '005.50'], + [0, '00', '00'], + + // Space alignment with ? + [1, '??', '01'], + [10, '??', '10'], + [1.5, '?.??', '1.50'], + [10.25, '?.??', '10.25'], + + // Escaped characters + [100, '\\#0', '#100'], + [50, '0\\%', '50%'], + [10, '0\\-', '10-'], + [25, '\\+0', '+25'], + + // Mixed format + [1234.5, '#,##0.00;[Red](#,##0.00)', '1,234.50'], + [-1234.5, '#,##0.00;[Red](#,##0.00)', '(1,234.50)'], + + // Additional important cases + [0.75, '0.#', '0.8'], + [100.123, '0.0', '100.1'], + [1234, '"Total: "#,##0', 'Total: 1,234'], + [0.5555, '0.00%', '55.55%'], + [999999, '#,##0', '999,999'], + [-0.25, '0.00;(0.00)', '(0.25)'], + + // Date format cases + [0.684027777777778, 'mm', '01'], + [0.684027777777778, '[mm]', '985'], + [0.684027777777778, '[h] "hours"', '16 hours'], + [0.684027777777778, '[h]:mm', '16:25'], + [0.684027777777778, '[h]:mm" ""minutes"', '16:25 minutes'], + [0.684027777777778, '[s]', '59100'], + [0.684027777777778, '[s]" ""seconds"', '59100 seconds'], + [0.684027777777778, '[ss].0', '59100.0'], + [0.684027777777778, '[mm]:ss', '985:00'], + [0.684027777777778, '[mm]:mm', '985:01'], + [0.684027777777778, '[hh]', '16'], + [0.684027777777778, '[h]:mm:ss.000', '16:25:00.000'], + [0.684027777777778, 'dd"d "hh"h "mm"m "ss"s"" "AM/PM', '00d 04h 25m 00s PM'], + [0.684027777777778, '[h]"h*"mm"m*"ss"s*"ss"ms"', '16h*25m*00s*00ms'], + [0.684027777777778, 'yyyy"Y-"mm"M-"dd"D "hh"H:"mm"M:"ss"."s"S"" "AM/PM', '1900Y-01M-00D 04H:25M:00.0S PM'], + [0.684027777777778, 'dd:mm:yyyy" "hh:mm:ss" "[hh]:[mm]" "AM/PM" ""minutes AM/PM"', '00:01:1900 04:25:00 04:985 PM minutes AM/PM'], + + [37753.6844097222, 'mm', '05'], + [37753.6844097222, '[mm]', '54365305'], + [37753.6844097222, '[h] "hours"', '906088 hours'], + [37753.6844097222, '[h]:mm', '906088:25'], + [37753.6844097222, '[h]:mm" ""minutes"', '906088:25 minutes'], + [37753.6844097222, '[s]', '3261918333'], + [37753.6844097222, '[s]" ""seconds"', '3261918333 seconds'], + [37753.6844097222, '[ss].0', '3261918333.0'], + [37753.6844097222, '[mm]:ss', '54365305:33'], + [37753.6844097222, '[mm]:mm', '54365305:05'], + [37753.6844097222, '[hh]', '906088'], + [37753.6844097222, '[h]:mm:ss.000', '906088:25:33.000'], + [37753.6844097222, 'dd"d "hh"h "mm"m "ss"s"" "AM/PM', '12d 04h 25m 33s PM'], + [37753.6844097222, '[h]"h*"mm"m*"ss"s*"ss"ms"', '906088h*25m*33s*33ms'], + [37753.6844097222, 'yyyy"Y-"mm"M-"dd"D "hh"H:"mm"M:"ss"."s"S"" "AM/PM', '2003Y-05M-12D 04H:25M:33.33S PM'], + [37753.6844097222, 'dd:mm:yyyy" "hh:mm:ss" "[hh]:[mm]" "AM/PM" ""minutes AM/PM"', '12:05:2003 04:25:33 04:54365305 PM minutes AM/PM'], + ]; + + for (let i = 0; i < testCases.length; i++) { + let value = testCases[i][0]; + let format = testCases[i][1]; + let expected = testCases[i][2]; + + let expr = new AscCommon.CellFormat(format); + let formatted = expr.format(value); + let text = ''; + for (let j = 0, length = formatted.length; j < length; ++j) { + text += formatted[j].text; + } + + assert.strictEqual(text, expected, `format("${format}", ${value})`); + } + }); + });