Skip to content

Commit

Permalink
fix(sheet): binary search (#1361)
Browse files Browse the repository at this point in the history
* fix(sheet): null value

* fix(sheet): binary search

* fix(sheet): lookup compatibility

* fix(sheet): lookup less equal result

* feat(sheet): animation ant
  • Loading branch information
DR-Univer committed Feb 19, 2024
1 parent 3422ee4 commit 23221c4
Show file tree
Hide file tree
Showing 6 changed files with 117 additions and 11 deletions.
59 changes: 59 additions & 0 deletions packages/engine-formula/src/engine/ast-node/function-node.ts
Expand Up @@ -66,6 +66,9 @@ export class FunctionNode extends BaseAstNode {
const variants: BaseValueObject[] = [];
const children = this.getChildren();
const childrenCount = children.length;

this._compatibility();

for (let i = 0; i < childrenCount; i++) {
const object = children[i].getValue();
if (object == null) {
Expand Down Expand Up @@ -96,6 +99,9 @@ export class FunctionNode extends BaseAstNode {
const variants: BaseValueObject[] = [];
const children = this.getChildren();
const childrenCount = children.length;

this._compatibility();

for (let i = 0; i < childrenCount; i++) {
const object = children[i].getValue();
if (object == null) {
Expand All @@ -115,6 +121,59 @@ export class FunctionNode extends BaseAstNode {
this.setValue(resultVariant as FunctionVariantType);
}

/**
* Compatibility handling for special functions.
*/
private _compatibility() {
this._lookupCompatibility();
}

/**
* The LOOKUP function follows the following rules when dealing with vectors of different sizes:
* If the lookup_vector is larger than the result_vector,
* the LOOKUP function will ignore the extra portion of the lookup_vector and only use the portion of the result_vector that is the same size as the lookup_vector for lookup and returning results.
* If the lookup_vector is smaller than the result_vector,
* the LOOKUP function will continue using the last value of the result_vector for lookup and returning results after the last value of the lookup_vector.
*/
private _lookupCompatibility() {
const children = this.getChildren();
const childrenCount = children.length;

if (this._functionExecutor.name !== 'LOOKUP' || childrenCount !== 3) {
return;
}

const lookupVectorOrArray = children[1].getValue();

const resultVector = children[2].getValue();

if (!lookupVectorOrArray?.isReferenceObject() && !resultVector?.isReferenceObject()) {
return;
}

const lookupVectorOrArrayRange = (lookupVectorOrArray as BaseReferenceObject).getRangeData();

const resultVectorRange = (resultVector as BaseReferenceObject).getRangeData();

const { startRow, startColumn, endRow, endColumn } = lookupVectorOrArrayRange;

const lookupCountRow = endRow - startRow + 1;
const lookupCountColumn = endColumn - startColumn + 1;

const { startRow: reStartRow, startColumn: reStartColumn, endRow: reEndRow, endColumn: reEndColumn } = resultVectorRange;

const resultCountRow = reEndRow - reStartRow + 1;
const resultCountColumn = reEndColumn - reStartColumn + 1;

if (lookupCountRow !== resultCountRow) {
resultVectorRange.endRow += lookupCountRow - resultCountRow;
}

if (lookupCountColumn !== resultCountColumn) {
resultVectorRange.endColumn += lookupCountColumn - resultCountColumn;
}
}

private _calculate(variants: BaseValueObject[]) {
let resultVariant: NodeValueType;

Expand Down
Expand Up @@ -657,10 +657,10 @@ export class ArrayValueObject extends BaseValueObject {
return this._binarySearch(valueObject, stringArray, stringPosition, searchType);
}

let result = this._binarySearch(valueObject, numberArray, numberPosition, searchType);
if (result == null) {
result = this._binarySearch(valueObject, stringArray, stringPosition, searchType);
}
const result = this._binarySearch(valueObject, numberArray, numberPosition, searchType);
// if (result == null) {
// result = this._binarySearch(valueObject, stringArray, stringPosition, searchType);
// }
return result;

// const stringMatrix = stringArray.getArrayValue();
Expand Down
4 changes: 4 additions & 0 deletions packages/engine-formula/src/functions/lookup/lookup/index.ts
Expand Up @@ -28,6 +28,10 @@ export class Lookup extends BaseFunction {
lookupVectorOrArray: ArrayValueObject,
resultVector?: BaseValueObject
) {
if (lookupValue == null || lookupVectorOrArray == null) {
return new ErrorValueObject(ErrorType.NA);
}

if (lookupValue.isError()) {
return lookupValue;
}
Expand Down
4 changes: 4 additions & 0 deletions packages/engine-formula/src/functions/lookup/vlookup/index.ts
Expand Up @@ -27,6 +27,10 @@ export class Vlookup extends BaseFunction {
colIndexNum: BaseValueObject,
rangeLookup?: BaseValueObject
) {
if (lookupValue == null || tableArray == null || colIndexNum == null) {
return new ErrorValueObject(ErrorType.NA);
}

if (lookupValue.isError()) {
return lookupValue;
}
Expand Down
47 changes: 40 additions & 7 deletions packages/sheets-ui/src/services/selection/selection-shape.ts
Expand Up @@ -17,7 +17,7 @@
import type { IRangeWithCoord, ISelectionCellWithCoord, Nullable, ThemeService } from '@univerjs/core';
import { ColorKit, RANGE_TYPE } from '@univerjs/core';
import type { Scene } from '@univerjs/engine-render';
import { DEFAULT_SELECTION_LAYER_INDEX, FIX_ONE_PIXEL_BLUR_OFFSET, Group, Rect, TRANSFORM_CHANGE_OBSERVABLE_TYPE } from '@univerjs/engine-render';
import { cancelRequestFrame, DEFAULT_SELECTION_LAYER_INDEX, FIX_ONE_PIXEL_BLUR_OFFSET, Group, Rect, requestNewFrame, TRANSFORM_CHANGE_OBSERVABLE_TYPE } from '@univerjs/engine-render';
import type { ISelectionStyle, ISelectionWidgetConfig, ISelectionWithCoordAndStyle } from '@univerjs/sheets';
import {
getNormalSelectionStyle,
Expand Down Expand Up @@ -398,6 +398,8 @@ export class SelectionShape {
AutofillStroke = defaultStyle.AutofillStroke!,

strokeDash,

isAnimationDash,
} = style;

let {
Expand Down Expand Up @@ -474,19 +476,27 @@ export class SelectionShape {

if (strokeDash == null) {
this.dashRect.hide();
this._stopAntLineAnimation();
} else {
const dashRectWidth = style.strokeWidth * 4;
this.dashRect.transformByState({
height: endY - startY - strokeWidth / 2,
width: endX - startX - strokeWidth / 2,
strokeWidth,
left: strokeWidth / 2 - 1 / scale,
top: strokeWidth / 2 - 1 / scale,
height: endY - startY,
width: endX - startX,
strokeWidth: dashRectWidth,
left: -dashRectWidth / 2 + fixOnePixelBlurOffset,
top: -dashRectWidth / 2 + fixOnePixelBlurOffset,
});

this.dashRect.setProps({
strokeDashArray: [0, strokeDash],
strokeDashArray: [0, strokeDash / scale],
});

this._stopAntLineAnimation();

if (isAnimationDash !== false) {
this._startAntLineAnimation();
}

this.dashRect.show();
}

Expand Down Expand Up @@ -1064,4 +1074,27 @@ export class SelectionShape {
const { scaleX, scaleY } = this._scene.getAncestorScale();
return Math.max(scaleX, scaleY);
}

private _antLineOffset = 0;

private _antRequestNewFrame: number = -1;

private _stopAntLineAnimation() {
this._antLineOffset = 0;
cancelRequestFrame(this._antRequestNewFrame);
}

private _startAntLineAnimation() {
const scale = this._getScale();
this._antLineOffset += 0.5 / scale;
if (this._antLineOffset > 16 / scale) {
this._antLineOffset = 0;
}
this.dashRect.setProps({
strokeDashOffset: -this._antLineOffset,
});
this._antRequestNewFrame = requestNewFrame(() => {
this._startAntLineAnimation();
});
}
}
6 changes: 6 additions & 0 deletions packages/sheets/src/basics/selection.ts
Expand Up @@ -72,6 +72,12 @@ export interface ISelectionStyle {
* The dashed line of the selection border. Here, the dashed line is a numerical value, different from the canvas dashed line setting. It is implemented internally as [0, strokeDash]. Setting it to 8 will look more aesthetically pleasing.
*/
strokeDash?: number;

/**
* Enable 'marching ants' animation
*/
isAnimationDash?: boolean;

/**
* The fill color inside the selection. It needs to have a level of transparency, otherwise content in the covered area of the selection will be obscured.
*/
Expand Down

0 comments on commit 23221c4

Please sign in to comment.