Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add onBeforePasteCell event to excel copy buffer #1298

Merged
merged 6 commits into from
Jan 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/TOC.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
* [Custom Tooltip](grid-functionalities/custom-tooltip.md)
* [Context Menu](grid-functionalities/Context-Menu.md)
* [Custom Footer](grid-functionalities/Custom-Footer.md)
* [Excel Copy Buffer Plugin](grid-functionalities/excel-copy-buffer.md)
* [Export to Excel](grid-functionalities/Export-to-Excel.md)
* [Export to File (csv/txt)](grid-functionalities/Export-to-Text-File.md)
* [Grid Menu](grid-functionalities/Grid-Menu.md)
Expand Down
1 change: 1 addition & 0 deletions docs/events/Available-Events.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ handleOnHeaderMenuCommand(e) {
- `onCopyCells`
- `onCopyCancelled`
- `onPasteCells`
- `onBeforePasteCell`

#### SlickContextMenu (extension)
- `onContextMenuClearGrouping`
Expand Down
129 changes: 129 additions & 0 deletions docs/grid-functionalities/excel-copy-buffer.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
### Description
Just like Excel you can select multiple cell and copy (`Ctrl+C`) and paste to Excel (`Ctrl+V`). However what you must know is that this plugin evaluate every single cell by their values (the raw value unless you specify otherwise, continue reading for more info).

### Usage
All you need to do is enable the Grid Option `enableExcelCopyBuffer: true` and give it a try. From your grid, start selecting multiple cells with the mouse then copy (with `Ctrl+C`) and paste to Excel (with `Ctrl+V`)

##### Component
```typescript
this.columnDefinitions = [
{ id: 'title', name: 'Title', field: 'id' },
{ id: 'description', name: 'Description', field: 'description' },
{ id: 'duration', name: 'Duration (days)', field: 'duration', type: FieldType.number },
];
this.gridOptions = {
enableExcelCopyBuffer: true,
};
```

### Copy & Paste with Cell Formatter
What if you have a date in UTC format in your dataset but your grid shows it as a Date ISO format? In that case, you are using a Formatter (e.g. `formatter: Formatters.dateIso`) and you wish to use that formatter. Good news, that is supported with and to make is simpler for the implementation, we will use a flag that already exist which is `exportWithFormatter` and is used by the `Export to File` service (for more info, read [Wiki - Export to File](Export-to-Text-File.md)

The `exportWithFormatter` can be used in 2 ways, on each column definition independently or for the entire grid through it's grid option.
##### `exportWithFormatter` through each Column Definition
```typescript
this.columnDefinitions = [
{
id: 'start', name: 'Start', field: 'start',
formatter: Formatters.dateIso,
exportWithFormatter: true
},
{
id: 'finish', name: 'Finish', field: 'finish',
formatter: Formatters.dateIso,
exportWithFormatter: true
},
];

this.gridOptions = {
enableExcelCopyBuffer: true,
};
```

##### `exportWithFormatter` through Grid Options
```typescript
this.columnDefinitions = [
{ id: 'start', name: 'Start', field: 'start', formatter: Formatters.dateIso },
{ id: 'finish', name: 'Finish', field: 'finish', formatter: Formatters.dateIso },
];

this.gridOptions = {
enableExcelCopyBuffer: true,
exportOptions: {
// set at the grid option level, meaning all column will evaluate the Formatter (when it has a Formatter defined)
exportWithFormatter: true
},
};
```
#### Sanitize Formatter Ouput
In some cases a Formatter can be formed of HTML and that will end up showing in your Copy+Paste. You can simply use the `sanitizeDataExport` flag which will remove any HTML tags from the output. For an example below, let say that our first Title column are all displayed in bold in the grid (e.g. `<b>Title 1</b>`), we want to sanitize that output a regular text output (e.g. `Title 1`)

##### `exportWithFormatter` through each Column Definition
```typescript
this.columnDefinitions = [
{
id: 'title', name: 'Title', field: 'id',
formatter: Formatters.bold,
exportWithFormatter: true,
sanitizeDataExport: true
}
];

this.gridOptions = {
enableExcelCopyBuffer: true
};
```

##### `exportWithFormatter` through Grid Options
```typescript
this.columnDefinitions = [
{ id: 'title', name: 'Title', field: 'id', formatter: Formatters.bold }
];

this.gridOptions = {
enableExcelCopyBuffer: true,
exportOptions: {
exportWithFormatter: true,
sanitizeDataExport: true
},
};
```

### Disable pasting on specific columns
If you want to disable pasting values for specific columns you can deactivate it using the denyPaste property on the Column config.

```typescript
this.columnDefinitions = [
{
id: 'colA', name: 'Col A', field: 'col_a',
formatter: Formatters.bold,
exportWithFormatter: true,
sanitizeDataExport: true,
denyPaste: true // <------------
}
];
```

This will even work in situations where your table copy buffer stretches over disabled cells, by simply skipping them. So for the following config (x = paste disabled; o = paste enabled), pasting a 3 cell stretching table buffer will result in Col A and C being updated but ColB ignoring the paste and keeping its original value

Col A | Col B | Col C \
\---------------------\
&nbsp;&nbsp; o &nbsp;&nbsp; | &nbsp;&nbsp;&nbsp; x &nbsp;&nbsp; | &nbsp;&nbsp;&nbsp; o \
NEW | &nbsp;&nbsp;&nbsp; x &nbsp;&nbsp; | &nbsp;NEW

### Disable pasting on specific cells
If you need even more fine grained control, you can make use of the gridOption `onBeforePasteCell`:

```typescript
this.gridOptions = {
enableExcelCopyBuffer: true,
excelCopyBufferOptions: {
onBeforePasteCell: (e, args) => {
// e.g deny paste on first cell
return args.cell > 0;
}
}
};
```

This way you have full control, via the args parameters, to get a ref to the current row and cell being updated. Also keep in mind that while performing a buffered table paste (e.g three cols at once) and only one of them has a denying condition, the other cells paste will pass successfully.
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import {
type Column,
type DOMEvent,
emptyElement,
type Formatter,
Formatters,
type GridOption,
Expand Down
10 changes: 9 additions & 1 deletion examples/vite-demo-vanilla-bundle/src/examples/example19.html
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
<style>
.blocked-cell {
background: darkred!important;
color: #999;
}

</style>
<h3 class="title is-3">
Example 19 - ExcelCopyBuffer with Cell Selection
<span class="subtitle">(with Salesforce Theme)</span>
Expand All @@ -11,7 +18,8 @@ <h3 class="title is-3">
</h3>

<h5 class="title is-5 mb-3">
Grid - using <code>enableExcelCopyBuffer</code> which uses <code>SlickCellSelectionModel</code>
Grid - using <code>enableExcelCopyBuffer</code> which uses <code>SlickCellSelectionModel</code><br />
The complete first row and the cells C - E of the second row are not allowing to paste values.
</h5>
<h6 class="title is-6">
<button class="button is-small is-primary" onclick.delegate="togglePagination()"
Expand Down
22 changes: 20 additions & 2 deletions examples/vite-demo-vanilla-bundle/src/examples/example19.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,20 @@ export default class Example19 {
targetRange.textContent += JSON.stringify(slickRange);
}
});

const hash = {
0: {},
1: {
2: 'blocked-cell',
3: 'blocked-cell',
4: 'blocked-cell',
}
};
for ( let i = 0; i < NB_ITEMS; i++) {
hash[0][i] = 'blocked-cell';
}

this.sgb.slickGrid?.setCellCssStyles(`blocked-cells`, hash);
}

dispose() {
Expand Down Expand Up @@ -88,11 +102,15 @@ export default class Example19 {

// when using the ExcelCopyBuffer, you can see what the selection range is
enableExcelCopyBuffer: true,
// excelCopyBufferOptions: {
excelCopyBufferOptions: {
// onCopyCells: (e, args: { ranges: SelectedRange[] }) => console.log('onCopyCells', args.ranges),
// onPasteCells: (e, args: { ranges: SelectedRange[] }) => console.log('onPasteCells', args.ranges),
// onCopyCancelled: (e, args: { ranges: SelectedRange[] }) => console.log('onCopyCancelled', args.ranges),
// }
onBeforePasteCell: (_e, args) => {
// deny the whole first row and the cells C-E of the second row
return !(args.row === 0 || (args.row === 1 && args.cell > 2 && args.cell < 6));
}
}
};
}

Expand Down
Loading