Skip to content

Commit

Permalink
fix(formula): fix formula parameter assignment
Browse files Browse the repository at this point in the history
  • Loading branch information
wpxp123456 authored and wpxp123456 committed Aug 1, 2024
1 parent 5c38528 commit 8a9ee45
Show file tree
Hide file tree
Showing 96 changed files with 2,797 additions and 2,617 deletions.
6 changes: 3 additions & 3 deletions packages/engine-formula/src/basics/date.ts
Original file line number Diff line number Diff line change
Expand Up @@ -265,13 +265,13 @@ export function countWorkingDays(startDateSerialNumber: number, endDateSerialNum
export function getDateSerialNumberByWorkingDays(startDateSerialNumber: number, workingDays: number, weekend: number | string = 1, holidays?: number[]): (number | ErrorValueObject) {
const weekendArray = getWeekendArray(weekend);

startDateSerialNumber = Math.floor(startDateSerialNumber);
let targetDateSerialNumber = startDateSerialNumber;
const _startDateSerialNumber = Math.floor(startDateSerialNumber);
let targetDateSerialNumber = _startDateSerialNumber;

let days = Math.abs(workingDays);

for (let i = 1; i <= days; i++) {
const currentDateSerialNumber = workingDays < 0 ? startDateSerialNumber - i : startDateSerialNumber + i;
const currentDateSerialNumber = workingDays < 0 ? _startDateSerialNumber - i : _startDateSerialNumber + i;

if (currentDateSerialNumber < 0) {
return ErrorValueObject.create(ErrorType.NUM);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1370,15 +1370,18 @@ export class StringValueObject extends BaseValueObject {
if (typeof value === 'string') {
// Case sensitivity needs to be considered, most functions are case-insensitive, like VLOOKUP/HLOOKUP/XLOOKUP/MATCH/COUNTIF/COUNTIFS/SUMIF/SUMIFS/SEARCH/FIND(in SUBSTITUTE)
// A few functions are case-sensitive, like EXACT/FIND/FINDB/REPLACE/REPLACEB/MIDB
let _value = value;

if (!isCaseSensitive) {
currentValue = currentValue.toLocaleLowerCase();
value = value.toLocaleLowerCase();
_value = _value.toLocaleLowerCase();
}

if (isWildcard(value)) {
return this._checkWildcard(value, operator);
if (isWildcard(_value)) {
return this._checkWildcard(_value, operator);
}
result = this._compareString(currentValue, value, operator);

result = this._compareString(currentValue, _value, operator);
} else if (typeof value === 'number') {
result = this._compareNumber(operator);
} else if (typeof value === 'boolean') {
Expand Down
18 changes: 10 additions & 8 deletions packages/engine-formula/src/functions/base-function.ts
Original file line number Diff line number Diff line change
Expand Up @@ -147,26 +147,28 @@ export class BaseFunction extends Disposable {
* @param indexNum
*/
getIndexNumValue(indexNum: BaseValueObject, defaultValue = 1) {
if (indexNum.isArray()) {
indexNum = (indexNum as ArrayValueObject).getFirstCell();
let _indexNum = indexNum;

if (_indexNum.isArray()) {
_indexNum = (_indexNum as ArrayValueObject).getFirstCell();
}

if (indexNum.isBoolean()) {
const colIndexNumV = indexNum.getValue() as boolean;
if (_indexNum.isBoolean()) {
const colIndexNumV = _indexNum.getValue() as boolean;
if (colIndexNumV === false) {
return ErrorValueObject.create(ErrorType.VALUE);
}

return defaultValue;
}
if (indexNum.isString()) {
const colIndexNumV = Number(indexNum.getValue() as string);
if (_indexNum.isString()) {
const colIndexNumV = Number(_indexNum.getValue() as string);
if (Number.isNaN(colIndexNumV)) {
return ErrorValueObject.create(ErrorType.REF);
}
return colIndexNumV;
} else if (indexNum.isNumber()) {
const colIndexNumV = indexNum.getValue() as number;
} else if (_indexNum.isNumber()) {
const colIndexNumV = _indexNum.getValue() as number;
return colIndexNumV;
}

Expand Down
64 changes: 32 additions & 32 deletions packages/engine-formula/src/functions/date/datedif/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,37 +27,41 @@ export class Datedif extends BaseFunction {
override maxParams = 3;

override calculate(startDate: BaseValueObject, endDate: BaseValueObject, unit: BaseValueObject) {
if (startDate.isArray()) {
startDate = (startDate as ArrayValueObject).get(0, 0) as BaseValueObject;
let _startDate = startDate;
let _endDate = endDate;
let _unit = unit;

if (_startDate.isArray()) {
_startDate = (_startDate as ArrayValueObject).get(0, 0) as BaseValueObject;
}

if (endDate.isArray()) {
endDate = (endDate as ArrayValueObject).get(0, 0) as BaseValueObject;
if (_endDate.isArray()) {
_endDate = (_endDate as ArrayValueObject).get(0, 0) as BaseValueObject;
}

if (unit.isArray()) {
unit = (unit as ArrayValueObject).get(0, 0) as BaseValueObject;
if (_unit.isArray()) {
_unit = (_unit as ArrayValueObject).get(0, 0) as BaseValueObject;
}

if (startDate.isError()) {
return startDate;
if (_startDate.isError()) {
return _startDate;
}

if (endDate.isError()) {
return endDate;
if (_endDate.isError()) {
return _endDate;
}

if (unit.isError()) {
return unit;
if (_unit.isError()) {
return _unit;
}

const startDateSerialNumber = getDateSerialNumberByObject(startDate);
const startDateSerialNumber = getDateSerialNumberByObject(_startDate);

if (typeof startDateSerialNumber !== 'number') {
return startDateSerialNumber;
}

let endDateSerialNumber = getDateSerialNumberByObject(endDate);
const endDateSerialNumber = getDateSerialNumberByObject(_endDate);

if (typeof endDateSerialNumber !== 'number') {
return endDateSerialNumber;
Expand All @@ -67,10 +71,14 @@ export class Datedif extends BaseFunction {
return ErrorValueObject.create(ErrorType.NUM);
}

if (!unit.isString()) {
if (!_unit.isString()) {
return ErrorValueObject.create(ErrorType.NUM);
}

return this._getResultByUnit(startDateSerialNumber, endDateSerialNumber, _unit);
}

private _getResultByUnit(startDateSerialNumber: number, endDateSerialNumber: number, unit: BaseValueObject): BaseValueObject {
const startDateDate = excelSerialToDate(startDateSerialNumber);
const startYear = startDateDate.getUTCFullYear();
const startMonth = startDateDate.getUTCMonth() + 1;
Expand All @@ -81,41 +89,33 @@ export class Datedif extends BaseFunction {
const endMonth = endDateDate.getUTCMonth() + 1;
const endDay = endDateDate.getUTCDate();

const unitValue = String(unit.getValue()).toLocaleUpperCase();
const unitValue = `${unit.getValue()}`.toLocaleUpperCase();

let result: number;
let _endDateSerialNumber;

switch (unitValue) {
case 'Y':
// The number of complete years in the period.
result = endYear - startYear;
break;
return NumberValueObject.create(endYear - startYear);
case 'M':
// The number of complete months in the period.
result = (endYear - startYear) * 12 + endMonth - startMonth;
break;
return NumberValueObject.create((endYear - startYear) * 12 + endMonth - startMonth);
case 'D':
// The number of days in the period.
result = Math.floor(endDateSerialNumber) - Math.floor(startDateSerialNumber);
break;
return NumberValueObject.create(Math.floor(endDateSerialNumber) - Math.floor(startDateSerialNumber));
case 'MD':
// The difference between the days in start_date and end_date. The months and years of the dates are ignored.
result = endDay - startDay;
break;
return NumberValueObject.create(endDay - startDay);
case 'YM':
// The difference between the months in start_date and end_date. The days and years of the dates are ignored.
result = endMonth - startMonth;
break;
return NumberValueObject.create(endMonth - startMonth);
case 'YD':
// The difference between the days of start_date and end_date. The years of the dates are ignored.
// The year is the year of the start date
endDateSerialNumber = excelDateSerial(new Date(Date.UTC(startYear, endMonth - 1, endDay)));
result = Math.floor(endDateSerialNumber) - Math.floor(startDateSerialNumber);
break;
_endDateSerialNumber = excelDateSerial(new Date(Date.UTC(startYear, endMonth - 1, endDay)));
return NumberValueObject.create(Math.floor(_endDateSerialNumber) - Math.floor(startDateSerialNumber));
default:
return ErrorValueObject.create(ErrorType.NUM);
}

return NumberValueObject.create(result);
}
}
112 changes: 57 additions & 55 deletions packages/engine-formula/src/functions/date/days360/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ export class Days360 extends BaseFunction {
override maxParams = 3;

override calculate(startDate: BaseValueObject, endDate: BaseValueObject, method?: BaseValueObject) {
const _method = method ?? BooleanValueObject.create(false);

if (startDate.isError()) {
return startDate;
}
Expand All @@ -36,29 +38,29 @@ export class Days360 extends BaseFunction {
return endDate;
}

if (method?.isError()) {
return method;
if (_method.isError()) {
return _method;
}

const maxRowLength = Math.max(
startDate.isArray() ? (startDate as ArrayValueObject).getRowCount() : 1,
endDate.isArray() ? (endDate as ArrayValueObject).getRowCount() : 1,
method?.isArray() ? (method as ArrayValueObject).getRowCount() : 1
_method.isArray() ? (_method as ArrayValueObject).getRowCount() : 1
);

const maxColumnLength = Math.max(
startDate.isArray() ? (startDate as ArrayValueObject).getColumnCount() : 1,
endDate.isArray() ? (endDate as ArrayValueObject).getColumnCount() : 1,
method?.isArray() ? (method as ArrayValueObject).getColumnCount() : 1
_method.isArray() ? (_method as ArrayValueObject).getColumnCount() : 1
);

const startDateArray = expandArrayValueObject(maxRowLength, maxColumnLength, startDate, ErrorValueObject.create(ErrorType.NA));
const endDateArray = expandArrayValueObject(maxRowLength, maxColumnLength, endDate, ErrorValueObject.create(ErrorType.NA));
const methodArray = method ? expandArrayValueObject(maxRowLength, maxColumnLength, method, ErrorValueObject.create(ErrorType.NA)) : [];
const methodArray = expandArrayValueObject(maxRowLength, maxColumnLength, _method, ErrorValueObject.create(ErrorType.NA));

const resultArray = startDateArray.map((startDateObject, rowIndex, columnIndex) => {
const endDateObject = endDateArray.get(rowIndex, columnIndex) as BaseValueObject;
let methodObject = method ? (methodArray as ArrayValueObject).get(rowIndex, columnIndex) as BaseValueObject : BooleanValueObject.create(false);
let methodObject = methodArray.get(rowIndex, columnIndex) as BaseValueObject;

if (startDateObject.isError()) {
return startDateObject;
Expand All @@ -80,10 +82,6 @@ export class Days360 extends BaseFunction {
return endDateSerialNumber;
}

if (methodObject.isError()) {
return methodObject;
}

if (methodObject.isString()) {
methodObject = methodObject.convertToNumberObjectValue();
}
Expand All @@ -92,61 +90,65 @@ export class Days360 extends BaseFunction {
return methodObject;
}

const startDateDate = excelSerialToDate(startDateSerialNumber);
const startYear = startDateSerialNumber > 0 ? startDateDate.getUTCFullYear() : 1900;
const startMonth = startDateSerialNumber > 0 ? startDateDate.getUTCMonth() + 1 : 1;
let startDay = startDateSerialNumber > 0 ? startDateDate.getUTCDate() : 0;

let endDateDate = excelSerialToDate(endDateSerialNumber);
let endYear = endDateSerialNumber > 0 ? endDateDate.getUTCFullYear() : 1900;
let endMonth = endDateSerialNumber > 0 ? endDateDate.getUTCMonth() + 1 : 1;
let endDay = endDateSerialNumber > 0 ? endDateDate.getUTCDate() : 0;
return this._getResult(startDateSerialNumber, endDateSerialNumber, methodObject);
});

const methodValue = +methodObject.getValue();
if (maxRowLength === 1 && maxColumnLength === 1) {
return (resultArray as ArrayValueObject).get(0, 0) as NumberValueObject;
}

if (!methodValue) {
// U.S. (NASD) method.
// If the starting date is the last day of a month, it becomes equal to the 30th day of the same month.
// If the ending date is the last day of a month and the starting date is earlier than the 30th day of a month, the ending date becomes equal to the 1st day of the next month; otherwise the ending date becomes equal to the 30th day of the same month.
if (startDay === 31) {
startDay = 30;
}
return resultArray;
}

if (endDay === 31) {
if (startDay < 30) {
endDateDate = excelSerialToDate(endDateSerialNumber + 1);
endYear = endDateDate.getUTCFullYear();
endMonth = endDateDate.getUTCMonth() + 1;
endDay = endDateDate.getUTCDate();
} else {
endDay = 30;
}
}
} else {
// European method. Starting dates and ending dates that occur on the 31st day of a month become equal to the 30th day of the same month.
if (startDay === 31) {
startDay = 30;
}
private _getResult(startDateSerialNumber: number, endDateSerialNumber: number, methodObject: BaseValueObject) {
const startDateDate = excelSerialToDate(startDateSerialNumber);
const startYear = startDateSerialNumber > 0 ? startDateDate.getUTCFullYear() : 1900;
const startMonth = startDateSerialNumber > 0 ? startDateDate.getUTCMonth() + 1 : 1;
let startDay = startDateSerialNumber > 0 ? startDateDate.getUTCDate() : 0;

let endDateDate = excelSerialToDate(endDateSerialNumber);
let endYear = endDateSerialNumber > 0 ? endDateDate.getUTCFullYear() : 1900;
let endMonth = endDateSerialNumber > 0 ? endDateDate.getUTCMonth() + 1 : 1;
let endDay = endDateSerialNumber > 0 ? endDateDate.getUTCDate() : 0;

const methodValue = +methodObject.getValue();

if (!methodValue) {
// U.S. (NASD) method.
// If the starting date is the last day of a month, it becomes equal to the 30th day of the same month.
// If the ending date is the last day of a month and the starting date is earlier than the 30th day of a month, the ending date becomes equal to the 1st day of the next month; otherwise the ending date becomes equal to the 30th day of the same month.
if (startDay === 31) {
startDay = 30;
}

if (endDay === 31) {
if (endDay === 31) {
if (startDay < 30) {
endDateDate = excelSerialToDate(endDateSerialNumber + 1);
endYear = endDateDate.getUTCFullYear();
endMonth = endDateDate.getUTCMonth() + 1;
endDay = endDateDate.getUTCDate();
} else {
endDay = 30;
}
}
} else {
// European method. Starting dates and ending dates that occur on the 31st day of a month become equal to the 30th day of the same month.
if (startDay === 31) {
startDay = 30;
}

const daysInYears = (endYear - startYear) * 360;
const daysInStartMonth = endDateSerialNumber >= startDateSerialNumber ? 30 - startDay : -startDay;
const daysInEndMonth = endDateSerialNumber >= startDateSerialNumber ? endDay : endDay - 30;
const daysInMidMonths = (endDateSerialNumber >= startDateSerialNumber ? (endMonth - startMonth - 1) : (endMonth - startMonth + 1)) * 30;

const totalDays = daysInYears + daysInStartMonth + daysInEndMonth + daysInMidMonths;
if (endDay === 31) {
endDay = 30;
}
}

return NumberValueObject.create(totalDays);
});
const daysInYears = (endYear - startYear) * 360;
const daysInStartMonth = endDateSerialNumber >= startDateSerialNumber ? 30 - startDay : -startDay;
const daysInEndMonth = endDateSerialNumber >= startDateSerialNumber ? endDay : endDay - 30;
const daysInMidMonths = (endDateSerialNumber >= startDateSerialNumber ? (endMonth - startMonth - 1) : (endMonth - startMonth + 1)) * 30;

if (maxRowLength === 1 && maxColumnLength === 1) {
return (resultArray as ArrayValueObject).get(0, 0) as NumberValueObject;
}
const totalDays = daysInYears + daysInStartMonth + daysInEndMonth + daysInMidMonths;

return resultArray;
return NumberValueObject.create(totalDays);
}
}
12 changes: 5 additions & 7 deletions packages/engine-formula/src/functions/date/edate/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,18 +78,16 @@ export class Edate extends BaseFunction {

const monthsValue = Math.floor(+monthsValueObject.getValue());

const startDate = excelSerialToDate(startDateSerial);
const _startDate = excelSerialToDate(startDateSerial);

const year = startDate.getUTCFullYear();
const month = startDate.getUTCMonth() + monthsValue;
const day = startDate.getUTCDate();
const year = _startDate.getUTCFullYear();
const month = _startDate.getUTCMonth() + monthsValue;
const day = _startDate.getUTCDate();

const resultDate = new Date(Date.UTC(year, month, day));
const currentSerial = excelDateSerial(resultDate);

const valueObject = NumberValueObject.create(currentSerial, DEFAULT_DATE_FORMAT);

return valueObject;
return NumberValueObject.create(currentSerial, DEFAULT_DATE_FORMAT);
});
}
}
Loading

0 comments on commit 8a9ee45

Please sign in to comment.