# Outlines

Outlines are workbook-local row and column groups. Use `univer run` to create or maintain them through the Pro Sheets Outline facade, then use facade readback to verify command-line results.

The outline facade is available in the headless runtime through `@univerjs-pro/sheets-outline/facade`.

## Core Workflow

Look up the workbook and worksheet, create row or column groups, then read them back with `getDimensionOutlines()`.

```bash
univer run ./budget.univer --code 'async () => {
  const workbook = univerAPI.getActiveWorkbook();
  const sheet = workbook.getSheetByName("Sheet1");
  if (!sheet) return { success: false, error: "Sheet1 not found" };

  sheet.getRange("A1:D6").setValues([
    ["region", "q1", "q2", "q3"],
    ["North", 10, 12, 14],
    ["South", 8, 9, 11],
    ["East", 7, 8, 9],
    ["West", 6, 7, 8],
    ["Total", 31, 36, 42]
  ]);

  sheet.addRowOutline(1, 4);
  sheet.addColumnOutline(1, 3);

  return {
    success: true,
    rowOutlines: sheet.getDimensionOutlines(univerAPI.Enum.DimensionOutlineAxis.ROW),
    columnOutlines: sheet.getDimensionOutlines(univerAPI.Enum.DimensionOutlineAxis.COLUMN)
  };
}'
```

Always verify with `getDimensionOutlines()` after a write. Do not edit private outline resource internals.

## Axis Enum Values

Use `univerAPI.Enum.DimensionOutlineAxis` when an API needs an axis.

The enum values are `ROW = "row"` and `COLUMN = "column"`.

| Facade enum value                            | Runtime value | Targets         |
| -------------------------------------------- | ------------- | --------------- |
| `univerAPI.Enum.DimensionOutlineAxis.ROW`    | `"row"`       | Row outlines    |
| `univerAPI.Enum.DimensionOutlineAxis.COLUMN` | `"column"`    | Column outlines |

The short form below is useful inside scripts:

```javascript
const axis = univerAPI.Enum.DimensionOutlineAxis;

return {
  rowAxis: axis.ROW,
  columnAxis: axis.COLUMN
};
```

## Row Groups

Create row groups with `sheet.addRowOutline(startRow, numRows)`.

`startRow` is zero-based. `numRows` is a count, not an inclusive end index. For example, `addRowOutline(1, 4)` groups rows 2 through 5.

```javascript
const workbook = univerAPI.getActiveWorkbook();
const sheet = workbook.getSheetByName("Sheet1");
if (!sheet) throw new Error("Sheet1 not found");

sheet.addRowOutline(1, 4);

return {
  rows: sheet.getDimensionOutlines(univerAPI.Enum.DimensionOutlineAxis.ROW).map((outline) => ({
    id: outline.id,
    axis: outline.axis,
    start: outline.start,
    end: outline.end,
    collapsed: outline.collapsed
  }))
};
```

## Column Groups

Create column groups with `sheet.addColumnOutline(startColumn, numColumns)`.

`startColumn` is zero-based. `numColumns` is a count, not an inclusive end index. For example, `addColumnOutline(1, 3)` groups columns B through D.

```javascript
const axis = univerAPI.Enum.DimensionOutlineAxis;

sheet.addColumnOutline(1, 3);

return {
  columns: sheet.getDimensionOutlines(axis.COLUMN).map((outline) => ({
    id: outline.id,
    axis: outline.axis,
    start: outline.start,
    end: outline.end,
    collapsed: outline.collapsed
  }))
};
```

## Readback

`getDimensionOutlines(axis?)` returns a snapshot of current outline data.

- Pass `univerAPI.Enum.DimensionOutlineAxis.ROW` to read row outlines.
- Pass `univerAPI.Enum.DimensionOutlineAxis.COLUMN` to read column outlines.
- Omit the axis to read both row and column outlines.

```javascript
const axis = univerAPI.Enum.DimensionOutlineAxis;
const allOutlines = sheet.getDimensionOutlines();
const rowOutlines = sheet.getDimensionOutlines(axis.ROW);
const columnOutlines = sheet.getDimensionOutlines(axis.COLUMN);

return {
  allCount: allOutlines.length,
  rowCount: rowOutlines.length,
  columnCount: columnOutlines.length
};
```

## Collapse And Expand

Use `setDimensionOutlineCollapsed(outlineId, collapsed)` to collapse or expand an existing group. Pass `true` to collapse and `false` to expand.

```javascript
const axis = univerAPI.Enum.DimensionOutlineAxis;
const [rowOutline] = sheet.getDimensionOutlines(axis.ROW);

if (rowOutline) {
  sheet.setDimensionOutlineCollapsed(rowOutline.id, true);
}

const [collapsed] = sheet.getDimensionOutlines(axis.ROW);

return {
  id: collapsed?.id,
  collapsed: collapsed?.collapsed
};
```

## Remove One Outline

Use `removeDimensionOutline(outlineId)` when you already know the outline id.

```javascript
const axis = univerAPI.Enum.DimensionOutlineAxis;
const [columnOutline] = sheet.getDimensionOutlines(axis.COLUMN);

if (columnOutline) {
  sheet.removeDimensionOutline(columnOutline.id);
}

return {
  remainingColumnOutlines: sheet.getDimensionOutlines(axis.COLUMN).length
};
```

## Outline Depth

There is no Facade API for setting an outline group's level or depth manually. The outline level is calculated by Univer from the created outline ranges. Nested groups become deeper levels when their ranges are fully contained by parent groups.

Create the group ranges you need, then use `getDimensionOutlines()` readback to verify the resulting groups. Do not invent APIs such as `setOutlineLevel()` or edit internal resource data to force a level.

## Clear Outlines

Use `clearDimensionOutlines(axis, start, end)` to clear outline groups on one axis. The `start` and `end` values are zero-based and inclusive.

The clear range must fully contain every target outline range. A clear range that partially overlaps an outline group is a failed or not-clearable operation; it does not partially delete or clip the group.

```javascript
const axis = univerAPI.Enum.DimensionOutlineAxis;

sheet.addRowOutline(1, 4);

// Does not fully contain the group from 1 through 4.
sheet.clearDimensionOutlines(axis.ROW, 2, 3);
const afterPartialOverlap = sheet.getDimensionOutlines(axis.ROW);

// Fully contains the group from 1 through 4.
sheet.clearDimensionOutlines(axis.ROW, 1, 4);
const afterFullClear = sheet.getDimensionOutlines(axis.ROW);

return {
  partialOverlapDidNotDelete: afterPartialOverlap.length === 1,
  fullClearDeleted: afterFullClear.length === 0
};
```

## Constraints

Outline APIs follow Univer's outline rules:

- ranges must be valid and in bounds
- row and column indexes are zero-based
- `addRowOutline()` and `addColumnOutline()` use a count argument
- crossing groups are not allowed
- nested groups are limited by maximum outline depth
- outline group levels are calculated automatically from nested ranges
- clear operations require the clear range to fully contain the target outline range

Use public readback from `getDimensionOutlines()` for verification. Do not mutate objects returned by readback and do not edit workbook resource internals directly.

## Related Topics

- See `sheets` for worksheet creation, row or column structure, and visibility.
- See `ranges` for direct range read/write APIs.
- See `formatting` for presentation changes inside grouped rows or columns.
