UPDATE: Merge cells

This commit is contained in:
Nicolás Hatcher
2025-03-01 11:21:00 +01:00
parent c554d929f4
commit 48727b1b39
21 changed files with 513 additions and 57 deletions

View File

@@ -40,6 +40,8 @@ import {
ArrowMiddleFromLine,
DecimalPlacesDecreaseIcon,
DecimalPlacesIncreaseIcon,
MergeCellsIcon,
UnmergeCellsIcon,
} from "../../icons";
import { theme } from "../../theme";
import BorderPicker from "../BorderPicker/BorderPicker";
@@ -74,6 +76,8 @@ type ToolbarProperties = {
onClearFormatting: () => void;
onIncreaseFontSize: (delta: number) => void;
onDownloadPNG: () => void;
onMergeCells: () => void;
onUnmergeCells: () => void;
fillColor: string;
fontColor: string;
fontSize: number;
@@ -429,6 +433,28 @@ function Toolbar(properties: ToolbarProperties) {
>
<ImageDown />
</StyledButton>
<StyledButton
type="button"
$pressed={false}
disabled={!canEdit}
onClick={() => {
properties.onMergeCells();
}}
title={t("toolbar.merge_cells")}
>
<MergeCellsIcon />
</StyledButton>
<StyledButton
type="button"
$pressed={false}
disabled={!canEdit}
onClick={() => {
properties.onUnmergeCells();
}}
title={t("toolbar.unmerge_cells")}
>
<UnmergeCellsIcon />
</StyledButton>
<ColorPicker
color={properties.fontColor}

View File

@@ -611,6 +611,29 @@ const Workbook = (props: { model: Model; workbookState: WorkbookState }) => {
downloadLink.download = "ironcalc.png";
downloadLink.click();
}}
onMergeCells={() => {
const {
sheet,
range: [rowStart, columnStart, rowEnd, columnEnd],
} = model.getSelectedView();
const row = Math.min(rowStart, rowEnd);
const column = Math.min(columnStart, columnEnd);
const width = Math.abs(columnEnd - columnStart) + 1;
const height = Math.abs(rowEnd - rowStart) + 1;
model.mergeCells(sheet, row, column, width, height);
setRedrawId((id) => id + 1);
}}
onUnmergeCells={() => {
const {
sheet,
range: [rowStart, columnStart, rowEnd, columnEnd],
} = model.getSelectedView();
const row = Math.min(rowStart, rowEnd);
const column = Math.min(columnStart, columnEnd);
model.unmergeCells(sheet, row, column);
setRedrawId((id) => id + 1);
}}
onBorderChanged={(border: BorderOptions): void => {
const {
sheet,

View File

@@ -386,10 +386,29 @@ export default class WorksheetCanvas {
column: number,
x: number,
y: number,
width: number,
height: number,
width1: number,
height1: number,
): void {
const selectedSheet = this.model.getSelectedSheet();
const structure = this.model.getCellStructure(selectedSheet, row, column);
if (typeof structure === 'object' && 'Merged' in structure) {
// We don't render merged cells
return;
}
let width = width1;
let height = height1;
if (typeof structure === 'object' && 'MergedRoot' in structure) {
const root = structure.MergedRoot;
const columns = root.width;
const rows = root.height;
for (let i = 1; i < columns; i += 1) {
width += this.getColumnWidth(selectedSheet, column + i);
}
for (let i = 1; i < rows; i += 1) {
height += this.getRowHeight(selectedSheet, row + i);
}
};
const style = this.model.getCellStyle(selectedSheet, row, column);
let backgroundColor = "#FFFFFF";

View File

@@ -23,6 +23,9 @@ import InsertRowBelow from "./insert-row-below.svg?react";
import IronCalcIcon from "./ironcalc_icon.svg?react";
import IronCalcLogo from "./orange+black.svg?react";
import MergeCellsIcon from "./merge-cells.svg?react";
import UnmergeCellsIcon from "./unmerge-cells.svg?react";
import Fx from "./fx.svg?react";
export {
@@ -47,5 +50,7 @@ export {
InsertRowBelow,
IronCalcIcon,
IronCalcLogo,
MergeCellsIcon,
UnmergeCellsIcon,
Fx,
};

View File

@@ -0,0 +1,4 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M8 2L3.33333 2C2.59695 2 2 2.59695 2 3.33333L2 5M8 2L12.6667 2C13.403 2 14 2.59695 14 3.33333L14 5M8 2L8 5M8 14L12.6667 14C13.403 14 14 13.403 14 12.6667L14 11M8 14L3.33333 14C2.59695 14 2 13.403 2 12.6667L2 11M8 14L8 11M2 5L2 11M2 5L14 5M2 11L14 11M14 5L14 11" stroke="#333333" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M5 8L11 8M5 8L6 9L6 7L5 8ZM11 8L10 7L10 9L11 8Z" stroke="#333333" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 564 B

View File

@@ -0,0 +1,5 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M8 2L3.33333 2C2.59695 2 2 2.59695 2 3.33333L2 5M8 2L12.6667 2C13.403 2 14 2.59695 14 3.33333L14 5M8 2L8 5M8 14L12.6667 14C13.403 14 14 13.403 14 12.6667L14 11M8 14L3.33333 14C2.59695 14 2 13.403 2 12.6667L2 11M8 14L8 11M2 5L2 11M2 5L14 5M2 11L14 11M14 5L14 11" stroke="#333333" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M2 8L6 8M6 8L5 7L5 9L6 8Z" stroke="#333333" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M14 8L10 8M10 8L11 7L11 9L10 8Z" stroke="#333333" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 650 B

View File

@@ -27,6 +27,8 @@
"vertical_align_top": "Align top",
"selected_png": "Export Selected area as PNG",
"wrap_text": "Wrap text",
"merge_cells": "Merge cells",
"unmerge_cells": "Unmerge cells",
"format_menu": {
"auto": "Auto",
"number": "Number",