diff --git a/examples/src/data/sheets/demo/default-workbook-data-demo.ts b/examples/src/data/sheets/demo/default-workbook-data-demo.ts index 526fda4cf37..9ec5bcf3e4a 100644 --- a/examples/src/data/sheets/demo/default-workbook-data-demo.ts +++ b/examples/src/data/sheets/demo/default-workbook-data-demo.ts @@ -13811,6 +13811,62 @@ export const DEFAULT_WORKBOOK_DATA_DEMO: IWorkbookData = { }, }, }, + uJSelZ11: { + bd: { + r: { + s: 1, + cl: { + rgb: 'rgb(0,0,0)', + }, + }, + b: { + cl: { + rgb: 'rgb(0,0,0)', + }, + s: 1, + }, + t: { + cl: { + rgb: 'rgb(0,0,0)', + }, + s: 1, + }, + l: { + cl: { + rgb: 'rgb(0,0,0)', + }, + s: 1, + }, + }, + }, + uJSelZ22: { + bd: { + r: { + s: 1, + cl: { + rgb: 'rgb(255,255,255)', + }, + }, + b: { + cl: { + rgb: 'rgb(255,255,255)', + }, + s: 1, + }, + t: { + cl: { + rgb: 'rgb(255,255,255)', + }, + s: 1, + }, + l: { + cl: { + rgb: 'rgb(255,255,255)', + }, + s: 1, + }, + }, + }, }, appVersion: '3.0.0-alpha', sheets: { @@ -13829,6 +13885,34 @@ export const DEFAULT_WORKBOOK_DATA_DEMO: IWorkbookData = { v: 'A Schedule of Items', }, }, + 5: { + 5: { + s: 'uJSelZ11', + }, + 6: { + s: 'uJSelZ11', + }, + 7: { + s: 'uJSelZ11', + }, + 8: { + s: 'uJSelZ11', + }, + }, + 6: { + 5: { + s: 'uJSelZ22', + }, + 6: { + s: 'uJSelZ22', + }, + 7: { + s: 'uJSelZ22', + }, + 8: { + s: 'uJSelZ22', + }, + }, }, freeze: { xSplit: 0, diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index 7348ae4549b..83a8f9c43f9 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -145,4 +145,6 @@ export { textEncoder } from './services/snapshot/snapshot-utils'; export { type ILogContext } from './services/log/context'; export { b64DecodeUnicode, b64EncodeUnicode } from './shared/coder'; +export { isBlackColor, isWhiteColor } from './shared/color/color-kit'; + installShims(); diff --git a/packages/core/src/shared/color/color-kit.ts b/packages/core/src/shared/color/color-kit.ts index 5f439ed3065..7b21c45715d 100644 --- a/packages/core/src/shared/color/color-kit.ts +++ b/packages/core/src/shared/color/color-kit.ts @@ -854,3 +854,64 @@ const rgb2Hsv: (color: IRgbColor) => IHsvColor = (color) => { const isUndefinedOrNull = (value: unknown): value is null | undefined => value == null; const isObject = (value: unknown): value is object => !isUndefinedOrNull(value) && typeof value === 'object'; + +export function isBlackColor(color: string): boolean { + // Regular expressions match different color formats. + const hexRegex = /^#(?:[0]{3}|[0]{6})\b/; + const rgbRegex = /^rgb\s*\(\s*0+\s*,\s*0+\s*,\s*0+\s*\)$/; + const rgbaRegex = /^rgba\s*\(\s*0+\s*,\s*0+\s*,\s*0+\s*,\s*(1|1\.0*|0?\.\d+)\)$/; + const hslRegex = /^hsl\s*\(\s*0*\s*,\s*0%*\s*,\s*0%*\s*\)$/; + const hslaRegex = /^hsla\s*\(\s*0*\s*,\s*0%*\s*,\s*0%*\s*,\s*(1|1\.0*|0?\.\d+)\)$/; + + if (hexRegex.test(color)) { + return true; + } + if (rgbRegex.test(color)) { + return true; + } + + if (rgbaRegex.test(color)) { + return true; + } + + if (hslRegex.test(color)) { + return true; + } + + if (hslaRegex.test(color)) { + return true; + } + + return false; +} + +export function isWhiteColor(color: string): boolean { + // Regular expressions match different color formats. + const hexRegex = /^#(?:[Ff]{3}|[Ff]{6})\b/; + const rgbRegex = /^rgb\s*\(\s*255\s*,\s*255\s*,\s*255\s*\)$/; + const rgbaRegex = /^rgba\s*\(\s*255\s*,\s*255\s*,\s*255\s*,\s*(1|1\.0*|0?\.\d+)\)$/; + const hslRegex = /^hsl\s*\(\s*0*\s*,\s*0%*\s*,\s*100%*\s*\)$/; + const hslaRegex = /^hsla\s*\(\s*0*\s*,\s*0%*\s*,\s*100%*\s*,\s*(1|1\.0*|0?\.\d+)\)$/; + + if (hexRegex.test(color)) { + return true; + } + + if (rgbRegex.test(color)) { + return true; + } + + if (rgbaRegex.test(color)) { + return true; + } + + if (hslRegex.test(color)) { + return true; + } + + if (hslaRegex.test(color)) { + return true; + } + + return false; +} diff --git a/packages/engine-render/src/components/sheets/sheet-skeleton.ts b/packages/engine-render/src/components/sheets/sheet-skeleton.ts index f0d4d4632fc..d4c21f72324 100644 --- a/packages/engine-render/src/components/sheets/sheet-skeleton.ts +++ b/packages/engine-render/src/components/sheets/sheet-skeleton.ts @@ -45,6 +45,7 @@ import { HorizontalAlign, isEmptyCell, isNullCell, + isWhiteColor, ObjectMatrix, searchArray, Tools, @@ -1802,6 +1803,24 @@ export class SpreadsheetSkeleton extends Skeleton { borderCache.setValue(r, c, { [type]: {} }); } + /** + * https://github.com/dream-num/univer-pro/issues/344 + * Compatible with Excel's border rendering. + * When the top border of a cell and the bottom border of the cell above it (r-1) overlap, + * if the top border of cell r is white, then the rendering is ignored. + */ + if (type === BORDER_TYPE.TOP) { + const borderBottom = borderCache.getValue(r - 1, c)?.[BORDER_TYPE.BOTTOM]; + if (borderBottom && isWhiteColor(rgb)) { + return true; + } + } else if (type === BORDER_TYPE.LEFT) { + const borderRight = borderCache.getValue(r, c - 1)?.[BORDER_TYPE.RIGHT]; + if (borderRight && isWhiteColor(rgb)) { + return true; + } + } + borderCache.getValue(r, c)![type] = { type, style: props.s, diff --git a/packages/sheets/src/commands/commands/set-border-command.ts b/packages/sheets/src/commands/commands/set-border-command.ts index 6a9d679e5f2..76d1d7a10d9 100644 --- a/packages/sheets/src/commands/commands/set-border-command.ts +++ b/packages/sheets/src/commands/commands/set-border-command.ts @@ -290,19 +290,25 @@ export const SetBorderCommand: ICommand = { } if (top) { - //setBorderStyle(topRangeOut, { b: null }); + /** + * https://github.com/dream-num/univer-pro/issues/344 + * Compatible with Excel's border rendering. + * When the top border of a cell and the bottom border of the cell above it (r-1) overlap, + * if the top border of cell r is white, then the rendering is ignored. + */ + setBorderStyle(topRangeOut, { b: null }); setBorderStyle(topRange, { t: Tools.deepClone(border) }, true); } if (bottom) { - //setBorderStyle(bottomRangeOut, { t: null }); + setBorderStyle(bottomRangeOut, { t: null }); setBorderStyle(bottomRange, { b: Tools.deepClone(border) }, true); } if (left) { - //setBorderStyle(leftRangeOut, { r: null }); + setBorderStyle(leftRangeOut, { r: null }); setBorderStyle(leftRange, { l: Tools.deepClone(border) }, true); } if (right) { - //setBorderStyle(rightRangeOut, { l: null }); + setBorderStyle(rightRangeOut, { l: null }); setBorderStyle(rightRange, { r: Tools.deepClone(border) }, true); }