From 70082ad9ecc9ccfad7306ca811f59e21b89db22d Mon Sep 17 00:00:00 2001 From: Adithyan29 Date: Wed, 23 Jul 2025 18:33:36 +0530 Subject: [PATCH 1/3] 971536: Updated the UG documentation for clipboard --- blazor/spreadsheet/clipboard.md | 614 +++++++++++++++--- .../images/contextmenu-cut-copy.png | Bin 0 -> 25161 bytes .../spreadsheet/images/contextmenu-paste.png | Bin 0 -> 20049 bytes blazor/spreadsheet/images/cut-copy.png | Bin 0 -> 23785 bytes blazor/spreadsheet/images/paste.png | Bin 0 -> 24188 bytes 5 files changed, 525 insertions(+), 89 deletions(-) create mode 100644 blazor/spreadsheet/images/contextmenu-cut-copy.png create mode 100644 blazor/spreadsheet/images/contextmenu-paste.png create mode 100644 blazor/spreadsheet/images/cut-copy.png create mode 100644 blazor/spreadsheet/images/paste.png diff --git a/blazor/spreadsheet/clipboard.md b/blazor/spreadsheet/clipboard.md index cf9b29e7f2..da486e607e 100644 --- a/blazor/spreadsheet/clipboard.md +++ b/blazor/spreadsheet/clipboard.md @@ -9,78 +9,529 @@ documentation: ug # Clipboard in Blazor Spreadsheet component -The Spreadsheet provides support for clipboard operations such as **Cut**, **Copy**, and **Paste**. These operations can be enabled or disabled by setting the [`EnableClipboard`](https://help.syncfusion.com/cr/blazor/Syncfusion.Blazor.Spreadsheet.SfSpreadsheet.html#Syncfusion_Blazor_Spreadsheet_SfSpreadsheet_EnableClipboard) property in the Spreadsheet component. By default, the `EnableClipboard` property is set to **true**. +The Spreadsheet supports clipboard operations such as **Cut**, **Copy**, and **Paste**. These operations can be enabled or disabled using the [EnableClipboard](https://help.syncfusion.com/cr/blazor/Syncfusion.Blazor.Spreadsheet.SfSpreadsheet.html#Syncfusion_Blazor_Spreadsheet_SfSpreadsheet_EnableClipboard) property of the Spreadsheet component. By default, the `EnableClipboard` property is set to **true**. + +N> When `EnableClipboard` is set to **false**, the **Cut** and **Copy** options are removed from the user interface (Ribbon and Context Menu). In addition, shortcut keys (**Ctrl+C, Ctrl+X, Ctrl+V**) and API methods will not work. ## Cut -The cut operation removes data from a selected range of cells, rows, or columns in a sheet and places it on the clipboard for use elsewhere. +The cut operation removes data from selected cells, rows, or columns in a sheet and temporarily stores it on the clipboard for use elsewhere. Once pasted to a new location, the original content is removed, effectively allowing users to move data within the spreadsheet. + +### Cut operations via UI + +The cut operation can be performed through the user interface (UI) using any of the following methods: + +**Using the Ribbon** + +- Select a cell or range of cells to cut the content. +- Click the **Cut** button in the **Home** tab of the **Ribbon** toolbar. This will cut the selected cell or range. + +![Cut - Ribbon](images/cut-copy.png) + +**Using the Context Menu** + +- Select a cell or range of cells to cut the content. +- Right-click on the selected cell or range. +- Choose the **Cut** option from the context menu. + +![Cut - Context Menu](images/contextmenu-cut-copy.png) + +### Cut operations programmatically + +The [CutCellAsync](https://help.syncfusion.com/cr/blazor/Syncfusion.Blazor.Spreadsheet.SfSpreadsheet.html#Syncfusion_Blazor_Spreadsheet_SfSpreadsheet_CutCellAsync_System_String_) method allows performing cut operations within any sheet. This method copies the specified cell or range and its properties (including value, format, style, etc.) to the clipboard and removes it from the sheet. It supports multiple scenarios for cutting cells or ranges. Below are the details for each scenario, including code examples and parameter information. + +> The cut operation will not execute if invalid or out-of-boundary cell ranges are provided. Ensure that all cell addresses fall within the valid worksheet boundaries. + +**Cut active range** + +When this method is called without any parameters, it automatically cuts the content from the last selected range if an active selection exists. If no range is currently selected, it cuts the active cell. + +{% tabs %} +{% highlight razor %} + +@using Syncfusion.Blazor.Spreadsheet + + + + + + + +@code { + public byte[] DataSourceBytes { get; set; } + public SfSpreadsheet SpreadsheetInstance; + + protected override void OnInitialized() + { + string filePath = "wwwroot/Sample.xlsx"; + DataSourceBytes = File.ReadAllBytes(filePath); + } + + public async Task CutActiveCell() + { + // To cut from the current cell. + await SpreadsheetInstance.CutCellAsync(); + } +} + +{% endhighlight %} +{% endtabs %} + +**Cut specific range in active sheet** + +To cut content from specific cells in the current active sheet, provide cell address as a parameter to the `CutCellAsync` method. When you specify a cell or range, the Spreadsheet component will cut that content and place it on the clipboard, ready for pasting elsewhere. + +| Parameter | Type | Description | +|-------------|-------------------|-------------| +| cellAddress | string (optional) | Specifies which cell(s) to cut. Accepts either a single cell reference (e.g., `"A1"`) or a range (e.g., `"A1:B5"`) from the active sheet. If not provided, the currently selected cell or range will be cut. | + +{% tabs %} +{% highlight razor %} + +@using Syncfusion.Blazor.Spreadsheet + + + + + + + + +@code { + public byte[] DataSourceBytes { get; set; } + public SfSpreadsheet SpreadsheetInstance; + + protected override void OnInitialized() + { + string filePath = "wwwroot/Sample.xlsx"; + DataSourceBytes = File.ReadAllBytes(filePath); + } + + public async Task CutCell() + { + // To cut the specified cell. + await SpreadsheetInstance.CutCellAsync("A2"); + } + + public async Task CutRange() + { + // To cut a range of cells. + await SpreadsheetInstance.CutCellAsync("A1:D10"); + } +} + +{% endhighlight %} +{% endtabs %} + +**Cut specific range in different sheet** + +To cut content from a specific sheet, include the source sheet name along with the cell reference in the parameter to the `CutCellAsync()` method. When specifying a sheet name, use an exclamation mark (`!`) to separate it from the cell reference, and the Spreadsheet component will cut that content and place it on the clipboard, ready for pasting elsewhere. + +| Parameter | Type | Description | +|-------------|-------------------|-------------| +| cellAddress | string (optional) | Specifies which cell(s) to cut. Accepts either a single cell reference (e.g., `"Sheet1!A1"`) or a range (e.g., `"Sheet2!A1:C5"`) from a specific sheet. If not provided, the currently selected cell or range will be cut. | + +{% tabs %} +{% highlight razor %} + +@using Syncfusion.Blazor.Spreadsheet + + + + + + + + +@code { + public byte[] DataSourceBytes { get; set; } + public SfSpreadsheet SpreadsheetInstance; + + protected override void OnInitialized() + { + string filePath = "wwwroot/Sample.xlsx"; + DataSourceBytes = File.ReadAllBytes(filePath); + } -**Cutting Data in Spreadsheet** + public async Task CutCellFromSpecificSheet() + { + // The address, along with the sheet name, to be cut. + await SpreadsheetInstance.CutCellAsync("Sheet1!B2"); + } -The cut operation can be performed through the following methods: + public async Task CutRangeFromSpecificSheet() + { + // To cut a range from a specific sheet. + await SpreadsheetInstance.CutCellAsync("Sheet2!B3:E8"); + } +} -* Select the **Cut** button in the **HOME** tab of the Ribbon toolbar to execute the cut operation. -* Right-click and select the **Cut** option from the context menu. -* Press the keyboard shortcut `Ctrl + X`(Windows) or `Command + X`(Mac). -* Using the [`CutCellAsync`](https://help.syncfusion.com/cr/blazor/Syncfusion.Blazor.Spreadsheet.SfSpreadsheet.html#Syncfusion_Blazor_Spreadsheet_SfSpreadsheet_CutCellAsync_System_String_) method. +{% endhighlight %} +{% endtabs %} ## Copy -The copy operation copies data from a selected range of cells, rows, or columns in a sheet and places it on the clipboard for use elsewhere. +The copy operation duplicates data from a selected range of cells, rows, or columns within a sheet and temporarily stores it on the clipboard for use elsewhere. Unlike the **Cut** operation, copying retains the original content in its location. + +### Copy operations via UI + +The copy operation can be performed through the user interface (UI) using any of the following methods: + +**Using the Ribbon** + +- Select the cell or range to copy. +- Click the **Copy** button in the **Home** tab of the **Ribbon** toolbar. This will copy the current active cell or range. + +![Copy - Ribbon](images/cut-copy.png) + +**Using the Context Menu** + +- Select the cell or range to copy. +- Right-click on the selected cell or range. +- Choose the **Copy** option from the context menu. + +![Copy - Context Menu](images/contextmenu-cut-copy.png) + +### Copy operations programmatically + +The [CopyCellAsync](https://help.syncfusion.com/cr/blazor/Syncfusion.Blazor.Spreadsheet.SfSpreadsheet.html#Syncfusion_Blazor_Spreadsheet_SfSpreadsheet_CopyCellAsync_System_String_) method enables performing copy operations within any sheet. This method copies the specified cell or range along with its properties (including value, format, style, etc.) to the clipboard. It supports multiple scenarios for copying cells or ranges. Below are the details for each scenario, including code examples and parameter information. + +> The copy operation will not execute if invalid or out-of-boundary cell ranges are provided. Ensure that all cell addresses fall within the valid worksheet boundaries. + +**Copy active range** + +When this method is called without any parameters, the method automatically copies the content from the last selected range if an active selection exists. If no range is selected, it copies the active cell. + +{% tabs %} +{% highlight razor %} + +@using Syncfusion.Blazor.Spreadsheet + + + + + + + +@code { + public byte[] DataSourceBytes { get; set; } + public SfSpreadsheet SpreadsheetInstance; + + protected override void OnInitialized() + { + string filePath = "wwwroot/Sample.xlsx"; + DataSourceBytes = File.ReadAllBytes(filePath); + } + + public async Task CopyActiveCell() + { + // To copy from the current cell. + await SpreadsheetInstance.CopyCellAsync(); + } +} + +{% endhighlight %} +{% endtabs %} -**Copying Data in Spreadsheet** +**Copy specific range in active sheet** -The copy operation can be performed through the following methods: +To copy content from specific cells in the current active sheet, provide cell address as a parameter to the `CopyCellAsync` method. When you specify a cell or range, the Spreadsheet component will copy that content and place it on the clipboard, ready for pasting elsewhere. + +| Parameter | Type | Description | +|-------------|-------------------|-------------| +| cellAddress | string (optional) | Specifies which cell(s) to copy. Accepts either a single cell from the active sheet (e.g., `"A1"`) or a cell range (e.g., `"A1:B5"`). If not provided, the currently selected cell or range will be copied. | + +{% tabs %} +{% highlight razor %} + +@using Syncfusion.Blazor.Spreadsheet -* Select the **Copy** button in the **HOME** tab of the Ribbon toolbar to execute the copy operation. -* Right-click and select the **Copy** option from the context menu. -* Press the keyboard shortcut `Ctrl + C` (Windows) or `Command + C` (Mac). -* Using the [`CopyCellAsync`](https://help.syncfusion.com/cr/blazor/Syncfusion.Blazor.Spreadsheet.SfSpreadsheet.html#Syncfusion_Blazor_Spreadsheet_SfSpreadsheet_CopyCellAsync_System_String_) method. + + + + + + + +@code { + public byte[] DataSourceBytes { get; set; } + public SfSpreadsheet SpreadsheetInstance; + + protected override void OnInitialized() + { + string filePath = "wwwroot/Sample.xlsx"; + DataSourceBytes = File.ReadAllBytes(filePath); + } + + public async Task CopyCell() + { + // To copy the specified cell. + await SpreadsheetInstance.CopyCellAsync("A2"); + } + + public async Task CopyRange() + { + // To copy a range of cells. + await SpreadsheetInstance.CopyCellAsync("A1:D10"); + } +} + +{% endhighlight %} +{% endtabs %} + +**Copy specific range in different sheet** + +To copy content from a specific sheet, include the source sheet name along with the cell reference in the parameter to the `CopyCellAsync` method. When specifying a sheet name, use an exclamation mark (`!`) to separate it from the cell reference, and the Spreadsheet component will copy that content and place it on the clipboard, ready for pasting elsewhere. + +| Parameter | Type | Description | +|-------------|-------------------|-------------| +| cellAddress | string (optional) | Specifies which cell(s) to copy. Accepts either a single cell from a specific sheet (e.g., `"Sheet1!A1"`) or a cell range (e.g., `"Sheet2!A1:C5"`). If not provided, the currently selected cell or range will be copied. | + +{% tabs %} +{% highlight razor %} + +@using Syncfusion.Blazor.Spreadsheet + + + + + + + + +@code { + public byte[] DataSourceBytes { get; set; } + public SfSpreadsheet SpreadsheetInstance; + + protected override void OnInitialized() + { + string filePath = "wwwroot/Sample.xlsx"; + DataSourceBytes = File.ReadAllBytes(filePath); + } + + public async Task CopyCellFromSpecificSheet() + { + // The address, along with the sheet name, to be copied. + await SpreadsheetInstance.CopyCellAsync("Sheet1!B2"); + } + + public async Task CopyRangeFromSpecificSheet() + { + // To copy a range from a specific sheet. + await SpreadsheetInstance.CopyCellAsync("Sheet2!B3:E8"); + } +} + +{% endhighlight %} +{% endtabs %} ## Paste -The paste operation pastes data from the clipboard into a selected range of cells, rows, or columns. This includes all information such as values and formatting. +The paste operation inserts data from the clipboard into a selected range of cells, rows, or columns, retaining all relevant details such as values, formats, and styles. When performing a **Cut** followed by **Paste**, the clipboard is cleared after the data is transferred. In contrast, with a **Copy** followed by **Paste**, the clipboard contents remain available for reuse. + +External clipboard support is also provided, enabling users to paste content not only from within the spreadsheet but also from outside sources such as Google Sheets, Microsoft Excel, Word documents, plain text files, and web pages. + +### Paste operations via UI + +The paste operation can be performed through the user interface (UI) using any of the following methods: + +**Using the Ribbon** + +- Select a range of cells or click on a cell. +- Click the **Paste** button in the **Home** tab of the **Ribbon** toolbar. This will paste the values that were cut or copied from the clipboard into the selected range. If no values are on the clipboard, the **Paste** option will be disabled. + +![Paste - Ribbon](./images/cutcopypaste.png) -External clipboard functionality is supported. When using cut and paste, the clipboard is cleared after pasting. With copy and paste, the clipboard contents remain unchanged. +**Using the Context Menu** -**Pasting Data in Spreadsheet**: +- Select a range of cells or click on a cell. +- Right-click and choose the **Paste** option from the context menu. If no values are on the clipboard, the **Paste** option will be disabled. -The paste operation can be performed through the following methods: +![Paste - Context Menu](./images/contextcutcopypaste.png) -* Select the **Paste** button in the **HOME** tab of the Ribbon toolbar to execute the paste operation. -* Right-click and select the **Paste** option from the context menu. -* Press the keyboard shortcut `Ctrl + V` (Windows) or `Command + V` (Mac). -* Using the [`PasteCellAsync`](https://help.syncfusion.com/cr/blazor/Syncfusion.Blazor.Spreadsheet.SfSpreadsheet.html#Syncfusion_Blazor_Spreadsheet_SfSpreadsheet_PasteCellAsync_System_String_) method. +### Paste operations programmatically -> When using the keyboard shortcut keys for cut (`Ctrl + X`) or copy (`Ctrl + C`) from external sources, use the `Ctrl + V` shortcut to paste content into the Spreadsheet. +The [PasteCellAsync](https://help.syncfusion.com/cr/blazor/Syncfusion.Blazor.Spreadsheet.SfSpreadsheet.html#Syncfusion_Blazor_Spreadsheet_SfSpreadsheet_PasteCellAsync_System_String_) method pastes the clipboard content into a specified cell or range and preserves all associated properties (including value, format, style, etc.). -![UI showing context menu cut, copy and paste option](./images/contextcutcopypaste.png) +> The paste operation will not execute if invalid or out-of-boundary cell ranges are provided. Ensure that all cell addresses fall within the valid worksheet boundaries. -![UI showing ribbon cut, copy and paste option](./images/cutcopypaste.png) +**Paste to active range** + +When this method is called without any parameters, it automatically pastes the content to the last selected range if an active selection exists. If no range is selected, it pastes to the active cell. + +{% tabs %} +{% highlight razor %} + +@using Syncfusion.Blazor.Spreadsheet + + + + + + + +@code { + public byte[] DataSourceBytes { get; set; } + public SfSpreadsheet SpreadsheetInstance; + + protected override void OnInitialized() + { + string filePath = "wwwroot/Sample.xlsx"; + DataSourceBytes = File.ReadAllBytes(filePath); + } + + public async Task PasteActiveCell() + { + // To paste to the current cell. + await SpreadsheetInstance.PasteCellAsync(); + } +} + +{% endhighlight %} +{% endtabs %} + +**Paste to specific range in active sheet** + +To paste content into specific range in the current active sheet, provide the target cell address as a parameter to the `PasteCellAsync` method. You can specify either a single cell or a range of cells as the destination. When the source range (copied content) is larger than the specified target range, all data from the source will still be pasted, automatically extending beyond the specified target boundaries to accommodate all content. + +| Parameter | Type | Description | +|-------------|-------------------|-------------| +| cellAddress | string (optional) | Specifies the target cell(s) for pasting clipboard content. Accepts either a single cell (e.g., `"A1"`) or a cell range (e.g., `"A1:B5"`) from the active sheet. If not provided, the currently selected cell or range will be used as the paste destination. | + +{% tabs %} +{% highlight razor %} + +@using Syncfusion.Blazor.Spreadsheet + + + + + + + + + +@code { + public byte[] DataSourceBytes { get; set; } + public SfSpreadsheet SpreadsheetInstance; + + protected override void OnInitialized() + { + string filePath = "wwwroot/Sample.xlsx"; + DataSourceBytes = File.ReadAllBytes(filePath); + } + + public async Task PasteCell() + { + // To paste to the specified cell. + await SpreadsheetInstance.PasteCellAsync("A2"); + } + + public async Task PasteRange() + { + // To paste to the specified range. + await SpreadsheetInstance.PasteCellAsync("A2:B5"); + } + + // Copy a large range and paste to smaller range. + public async Task CopyLargerRangeThanTarget() + { + // Copy a 7-row range. + await SpreadsheetInstance.CopyCellAsync("F3:F9"); + + // Paste to a smaller 3-row range. All 7 rows will be pasted, extending beyond the specified range. + await SpreadsheetInstance.PasteCellAsync("A5:A7"); + } +} + +{% endhighlight %} +{% endtabs %} + +**Paste to specific range in different sheet** + +To paste content into a specific sheet, include the target sheet name along with the cell reference as a parameter to the `PasteCellAsync` method. When specifying a sheet name, use an exclamation mark (!) to separate it from the cell reference. When the source range (copied content) is larger than the specified target range, all data will still be pasted completely, extending beyond the specified target boundaries to accommodate all content. + +| Parameter | Type | Description | +|-------------|-------------------|-------------| +| cellAddress | string (optional) | Specifies the target cell(s) for pasting clipboard content. Accepts either a single cell from a specific sheet (e.g., `"Sheet1!A1"`) or a cell range (e.g., `"Sheet2!A1:C5"`). If not provided, the currently selected cell or range will be used as the paste destination. | + +{% tabs %} +{% highlight razor %} + +@using Syncfusion.Blazor.Spreadsheet + + + + + + + + +@code { + public byte[] DataSourceBytes { get; set; } + public SfSpreadsheet SpreadsheetInstance; + + protected override void OnInitialized() + { + string filePath = "wwwroot/Sample.xlsx"; + DataSourceBytes = File.ReadAllBytes(filePath); + } + + public async Task CopyPasteCellBetweenSheets() + { + // The address, along with the sheet name, to be pasted. + await SpreadsheetInstance.PasteCellAsync("Sheet1!B2"); + } + + // Copy from one sheet and paste to another without switching sheets. + public async Task CopyPasteRangeBetweenSheets() + { + // Copy value from "Sheet1". + await SpreadsheetInstance.CopyCellAsync("Sheet1!A1:A5"); + + // Paste to "Sheet2" without switching to it. + await SpreadsheetInstance.PasteCellAsync("Sheet2!C3"); + } +} + +{% endhighlight %} +{% endtabs %} + +## Events + +The Syncfusion Blazor Spreadsheet provides two events that are triggered during the clipboard action such as [CutCopyActionBegin](https://help.syncfusion.com/cr/blazor/Syncfusion.Blazor.Spreadsheet.CutCopyActionBeginEventArgs.html) and [Pasting](https://help.syncfusion.com/cr/blazor/Syncfusion.Blazor.Spreadsheet.PastingEventArgs.html). These events can be used to perform any custom actions before the clipboard action starts. + +* **CutCopyActionBegin** - [CutCopyActionBegin](https://help.syncfusion.com/cr/blazor/Syncfusion.Blazor.Spreadsheet.CutCopyActionBeginEventArgs.html) event is triggered before a cut or copy operation begins. +* **Pasting** - [Pasting](https://help.syncfusion.com/cr/blazor/Syncfusion.Blazor.Spreadsheet.PastingEventArgs.html) event is triggered before a paste operation begins. + +**CutCopyActionBegin Event** + +The `CutCopyActionBegin` event is triggered before a cut or copy operation begins. This event provides details about the operation and allows for cancellation if required. + + +**Event Arguments** + +The `CutCopyActionBeginEventArgs` includes the following properties: + +| Event Arguments | Description | +|----------------|-------------| +| Action | An enum value from the ClipboardAction class that indicates whether the operation is `ClipboardAction.Cut` or `ClipboardAction.Copy`. | +| CopiedRange | A string representing the range being copied, including the sheet name (e.g., "Sheet1!A1:B5"). | +| Cancel | A boolean value that can be set to true to prevent the operation. | {% tabs %} {% highlight razor tabtitle="Index.razor" %} @using Syncfusion.Blazor.Spreadsheet -@using Syncfusion.Blazor.SplitButtons - - - - - - - - - - - - + + + @code { public byte[] DataSourceBytes { get; set; } - public SfSpreadsheet SpreadsheetRef { get; set; } + public SfSpreadsheet SpreadsheetInstance { get; set; } protected override void OnInitialized() { @@ -88,57 +539,44 @@ The paste operation can be performed through the following methods: DataSourceBytes = File.ReadAllBytes(filePath); } - private async Task ItemSelected(MenuEventArgs args) + public void OnCutCopyActionBegin(CutCopyActionBeginEventArgs args) { - if (args.Item.Text == "Cut") - { - await SpreadsheetRef.CutCellAsync(); - } - - if (args.Item.Text == "Copy") - { - await SpreadsheetRef.CopyCellAsync(); - } - - if (args.Item.Text == "Paste") - { - await SpreadsheetRef.PasteCellAsync(); - } + // To cancel the cut or copy action. + args.Cancel = true; } } {% endhighlight %} {% endtabs %} -### Prevent pasting +**Pasting Event** + +The `Pasting` event is triggered before a paste operation begins. It provides information about the paste operation and allows you to validate or cancel it. + +**Event Arguments** -The following example illustrates how to prevent the paste action in the Spreadsheet. In the [`Pasting`](https://help.syncfusion.com/cr/blazor/Syncfusion.Blazor.Spreadsheet.PastingEventArgs.html) event, setting the `Cancel` argument to **true** prevents the paste operation. +The `PastingEventArgs` includes the following properties: + +| Event Arguments | Description | +|----------------|-------------| +| ExternalClipboardData | An array of strings containing raw text data from external sources (like Excel or Google Sheets), with each element representing a row of data. Set to null when copying from within the workbook. | +| CopiedRange | A string in the format "SheetName!Range" (e.g., "Sheet1!A1:A10") representing the source location of the copied or cut content. Set to null when pasting external content. | +| PasteRange | A string in the format "SheetName!Range" specifying the target cell range where content will be pasted. | +| Cancel | A boolean value that can be set to true to prevent the paste operation, allowing event handlers to control the paste behavior. The default value is false. | {% tabs %} {% highlight razor tabtitle="Index.razor" %} @using Syncfusion.Blazor.Spreadsheet -@using Syncfusion.Blazor.SplitButtons - - - - - - - - - - - - + + - + @code { public byte[] DataSourceBytes { get; set; } - - public SfSpreadsheet SpreadsheetRef { get; set; } + public SfSpreadsheet SpreadsheetInstance { get; set; } protected override void OnInitialized() { @@ -146,28 +584,26 @@ The following example illustrates how to prevent the paste action in the Spreads DataSourceBytes = File.ReadAllBytes(filePath); } - private async Task ItemSelected(MenuEventArgs args) + public void OnBeforePaste(PastingEventArgs args) { - if (args.Item.Text == "Cut") + // Prevent pasting into a specific range + if (args.PasteRange.Contains("A1:B5")) { - await SpreadsheetRef.CutCellAsync(); + args.Cancel = true; } - if (args.Item.Text == "Copy") + // Validate external content + if (args.ExternalClipboardData != null) { - await SpreadsheetRef.CopyCellAsync(); + foreach (var line in args.ExternalClipboardData) + { + if (line.Contains("Confidential")) + { + args.Cancel = true; + break; + } + } } - - if (args.Item.Text == "Paste") - { - await SpreadsheetRef.PasteCellAsync(); - } - } - - public void OnBeforePasteHandler(PastingEventArgs args) - { - // To cancel the paste action. - args.Cancel = true; } } diff --git a/blazor/spreadsheet/images/contextmenu-cut-copy.png b/blazor/spreadsheet/images/contextmenu-cut-copy.png new file mode 100644 index 0000000000000000000000000000000000000000..7ec37449a42eed3aa54fb9485ac9b81c723c928d GIT binary patch literal 25161 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%0AT&={OdUl7pyC;^ucxwbZvoT z^Nh^R+RcFxb~bCfbtVpxd`Zloi+&-`+?BSN@WrIwdC6Sfhu^dnnQHa`AhJqx$#2*G z1$s_ehK)*BWA{=E7jv#O*r}soK(-kJ6qP6hJ}Hd_V}R_{+G^^Gqze+E7&-zAADE_71ew538#?XQm> zW?mdI78utvn72lniY#mU`AGrg4aH{k)wpco0lXz)$P=!bNbD|LRRy*}=d_5%2pUMk!K0 zH|@u(LW=5+@sI*T{$5cbT9)z%Zgmi_^BS++p=+|RSb-7WH#X)i=xA^MuFP8-3{`tW z@0;R>uf9jl5#FoK`^~bi4Hax7peIq;)U*z4520sOSG|TB;nObA4NOa;gNtMm7B1D9 zt#EU51LD2BL*B26bQypTe86E5%0E0jTsuKo!cdm(HaHQPNUg7MLjgE0UH`47rY3&p zIYl~g*AJtQ(s4?Hb4Hv3fFArr_$dVi+l}ezY0uqGkzs4LNBK^>O?V*C9IoUS4Vgs{ zFiO+WM1_W895dOJ3c3vG2X@XYDyylzPU}f%w~+5U0nSL<8DP1*9}ORfmEpUi1abkm z1bBeyJ@<#LhB+^p8*h92+=55_7W5`zVc{Qe8+N;8V*dPjP;)Thg8*GWKfjnuPk`q6 z`uc)@Gx_Cia|pGKO|6~F__AH}H{g(tZ}WYcMKrcvupiL{x4M?s3T9=Es$Zd`WM*PQ z8!fYI`kBb(v{`!qt~);tJXQca#m@8hY$xmJktKiMz~Gm?{VM~Wws=-$gniD<%_;sw zsQ2-)H?+OmpSAG=D{E@#;Q7b>VMW(+aCzru)f7sIgOA^|J=KJ|Z*{sD*ycaSuq6f2N2F?K7q=Vwe9Tc|XRpduUM?Fu3*6br+Mn{AB-R21D zg-V9xBVD*g7**IZGBQYMuMT`}nrlzk9EEUwMWWMuGJ(Q#`^)>P$yvi=YgFw`(->)sBR5ez6vDXEZE%cD~bne#(t|I=-S zX)*Djth_vSJw3hT+T;ZokD!?0Q1Td%ynfvA8h0KL3HQRzmU*(+*H@`gY2o|XF z{_ZtorYKt=BG%g@MoJ{ZKzsRe@2ruNae28gVCC0u-dvAdG^+6=%~6PIbXgsc&F^=A zIu|cSc|5gIy%{Q(4SsZnv_A?HNBzzS(_QCBrs}<0KwJO{ry|AgQ0*lOPprq4T?U>K72^7 zZ!5g9v7uXTPhV(Id2KG}o~mky0Z*6#kAk%|CmtRiGRX`ooiX9g1_5BHrj;v*?%aoQ zA@myL91uY7KYH{+If4g$<4LNq|#O$G`cQK-6346d&On_04L38~!ohluI~W2_r>HKqG_$kJGT#`N(dK|Gk8USpSP}=g#XHm1Iv( z&CfAX4)f{+74-D=Q-5bED;kUTz4#XRX|-NX4u|RH?fJTx?TA|fIc)zwf; zzm^yNvNSV5?>b3gj#3|NN-FW{9U7cnbaP|_N>u>54=E|BE`S9%OF(%V4Djg*e(2VC@`H8()m&yf{5*kO9j{2|;lq&re4Ven(;Dz;H@LX) zVQir9sL{$b7o;<*0vd&G2ro5OK_9`7@$>aX(68PG*RGsl@nz$iJ$=vTx zEf5v^S6nOh?_a-EpkCk$biS0d%yKwUY$Cc?jHgzxC=j(?G`dM*vj!cm)KtX-%H8&% z+_4nUTc6n|5!8K#Tkb3J+sXEzBJAw!kWf;xzmh<&V(xr-$X}3TRbj8M9Smfv^ zB6@KPcXxj9BfNGO&`@BXF&`ct;CK2x8( z1~J@R&GtfPv3t4kFoGAPPq%IZFLJ~R3be7do_U*-Q>kO*6=LJyusAY0T3J?hv#_)@ zvD#&kD6el>G)lhdW50Fb$B!>;o;;a?yWp`tBJ6%ZarC!Oy)s?G!x=t?d*+)S_d%Y_ z*^6q|<;(gO+Rzz9+}CtXl~h$9=aW!6!jGtZeBca1k%5*LS)O*j7<}xqtM~@Ug9bJ> zT!RAxY~LQ%8g;w5x;oO+)61pa94Nbyn3>s)iH)uATa)zam1B-V%)-5U_bPyGtMMec zK);vs^7ogt=Ei?@c=`Fi62vHwCd?0yE$}FE%SQ!0TO|kqqo>}$dgU0S|VvvOzt3Uz8 z0A(OrtRyQd%l<2|#3g{bGuX#6XMeS(M;f57Qlg4omo?v)xfuc~)+sbF)j4>fmUsK! zJ-o}8FIO2X?4Is+n;&jX$GZi)=KY_l!3kWWa$;iQHt=ME?dYPwq1Z-0 ztE;O6(%A%P1NgxkXx`C`GDJb&Q9<9QdPU@6=0ZnwP5n|^SV#oQfTE%z zNhkwcVr+c;wK-QCd;35iX&g2L&OrROMVjaWToqj~@{T z3cV?0ueoZ?Pl09`m=mGswI%I`52tGnCYpM4l}p@KwE-7;P*c|Wo!kUl)W~}|m*;U= zBlbAAewiz+3O+u5TtWi#^4aB8(Dy-`vuhxg)hQY@U+hZ9!NEcLYOu0fGt5(j+*dR3 zy~Z%C%c}tx)7;wnrKR~LkU55Q#Z`8A2ZABS>ilTyPsTTkArnwwSgoz=zBxe%D=<$& z7g#)>-?1wT3yVerEBd89Eu3->dO9qVt=)o=WT*?j`x+ZsAIx(lXY7_na zza0RNs_XP#a5p|6(~6kEwTezPSoEHUSnnZSke`^*{>FF&xLu~9{8m61LJu$gb|uHX zBGF$3CqcSxDnrVrivH_5Pgn{Uh*Qi^l|Wz{@p)^eT(vq#&4~Z?+LC?+RD18O*w^oi z2nm^te0$pHX$PJ6rtQ$P=g%)adsB7)f1}98=J~>B;23P7AEDcgh|4v@&17M(MI?0) z)4=;Fc}RNY3I>4jNJbeWT@jms8=&;ksYitsff07vzbYTS= zD3fR2Rn3pYwA4Ma-e&w`V$UmnMN{^!Dt3+*g7OjTrHcurv~7sb>cG;cF}k{c3&=4L zBFm`#Ee8>9YO^l{&VX7k7Ryxz9&6bmt4im!ee;=Hdc4UwGNQ;uBBDI zcg`v~>Ob_NPs4=+^ga<%R8hI3qC!BBF4hYTf)(6p35&P$p`lpFX<2n=va@t)` z{qyG!M1g7JnPM}Z*x20m@sa2mw&CXCkvBDE!o$ahWYbe1$TZwsyu59ofW;woPy=o&518s{CPTH0j5@X5 zIFOaDe*0i9K^gNAICnWbKE8JKDhg&aLKxUolApmeGwaEc z<>2L208QE-K8*px^T@ipiIf51Cs6y#w80r zgQ)@0B`h>FG+VbBIqwAKs65S&#n3l^PwJ+b^ZkpWhKfytw!9-KxXtp#=n!0}PKRhi zVMO$ez&;=b#%T8aIp!J9R#|CjHY7_u#@#4;#4w29ab&f5l9bEHY2ogI zPyt-%u@DE@-~br7X1)%>oSZMYSF{Zb(&qL6{0IANRJN_H4wJ!=G&vKuc6SqmUj6u? z2>6s%wP5ilcm*4EC-z7ga{wv;a5ufYjO&WkyT9-5yWK(wFWymAB}7UHgnOm3*)aOn z7)D}sb@gn2Q`2m%^uwzI=1S2*bxGCM{h#btAI*I2mcH%jDGE!ejY5oQkp^;P)pU9ip5r=$a=-@Z9QM9RR$f22 zfU^>oI6^_R^83@|bC8eofZ{`Fij9p8*~llOqD4SW6(DzHtI`r+xtCKYsjDx-3F&BR zUMo<(cMoAXVx@ZA1s&bpo0>5XH8mTf7^JF3#eqi9p?H8la65CXEbEcVy#EI7CuTz~HE~_{tnERI4%Fgee{>v7B@edgi3GKIrgF*^- z=PD0R^mx?m-(&bUulg$=wau8c$&@XO;p-F`h1|=%)aC>u2BN715HA8rsTyM#bVakq zU|dHJkE8B&HrcD%>Q9IbD6umYiVs2H;iVJ zTMMZruK87O{;yL^Dq?X;j+-pOxI z$tZY@2omo-E*pCUtM8h*Sc;M7G$x&-CkZs=$JS)M^(Ai@fqX=D%W|kqGIz;7Dg5W1 z{O2R)RzH8=3C}?s<;);HK|!q_vdJKN{pz;)_bu0S+Tr_BL)Vb+$Ets$xqSIK1RL}W zHVB}5kji9kMDW&eq$!f+nX_A5Ex8*lbQ9au-kt|o-whrQuoOPu;Nc;{3X;_Yg?hy6jAn!sUV3P9L(e zP%!*Pi!<>akEm!edIK8CWleV=zuvVImM^a3mb{W8)7p8VcQnf+Dq7Lu)W!Dx zL4Lo1tE&)DVU~|=vk9s%DV=7NT;{u;y?6hHwypnDW})p{bBv*>bsNyWNO}nhaN3dz zy1Tks!CzJ}TC!K38SLunl6P|ApYYvP{W0%c_UR6g;0&(?YM?WipodvRU}IRNj5uX2 zC_*A~ruQ|kaWv$XzM>_GX2PE=Y-~gyo&l;o3j_5HmT$2|`(=31tmP&7A@n-v2Qnt` zcbL-6i0*4M$OFX6-9>JVhnw53fi)KcbNqZ7wrJ?q`%5)8HpV6-APGbBgN<=27?AQ& zG$G^F9_Fy>fH25{HaAdY90Nn>OZ74|287CbJW6`~Iuv*$2>Li7AtA|N3S7H(jf9*$ z1e6mzH#c$m`1p7dQqn+}y6u6<;6Q;^#C-kw#}0RthOTZnNZSB3Ol3|EHbsu~%-|!! zfkFc+(7zMj2{8oPVha^Y?O$>Gt+Wm%plu%(T^#e4{rI3Rb9Mz*Z_7%5{_tBK0JUJr zFc#;dq2RFc5aR<-fzXr4{FiNN=$9_V#>S#hKRP;^wx*lz!(o$*{i%U;Bcdm?)Cg)p zOOvA=ht-Ou|>&vRVK__;GTekrHMJ#$&H1S>wIRyoc zA&6;hPINl@`W9hf*qLw$D4mtwmReVZcNo@^r^*Zb2_+Wu7E_oll6eKhqKc z8SE;)nqspSybljJ;fcBTNh1OS;BWUDfA7&%UXWB5g`yAs3-kTxZ&d2R8yL@Ns$t;mI3N7dAyWU;W&MXlan*J zMO%jjZ~)?nDXOaGmKe;CTyZ@K1atK=42eUKyRrvYhs^?wirVrr{a?bikbL!KL8loA zJ8aetRX8zQ{z?vngeLxD=#sEw%Ohm*WPcqU1vVZzI6fNr{f**2$wE&rgZs;|bs22b zQQ}A{{!3tJaYBT!7^)y4DH7N&!NZ3SJ@@)`LX3)prS^x+k)_24m(lKRY-|iaAx9+* zrF9!(m2ma&1rj^LwqK3TzI^_IjNJ^R7u^!GmS;7#FGNWseynm7`d{O|e*MM23fYUf z;M<_VQPR_MkHu5b(fxX;qocomCqHb4#ejcE|A zHuf=SsCB(lm^*vvtbm}&iM2U3ijcdA4WwaWj!Taeo1#M_aD+f9Pl6z-`2IQa$a>Ta~4Q?#&^tZaGAf0!=h z56f`w<$mc1?gX=o7j&?#agRx*m8vfg00v>o_01J*6mXDeh+O=he}uu8z}z_^)-^XxF#`o>WOu!{O4Uy#wwg3b<_sp0Z+kbi8(f05eYoIkILY>@_?sL zX9ZDn-3rHSzE_A{79Za`zk-qXD}qf9Zi;|_z}19yq&))X0EYX$vy%{_yhxU~&hG?v zAmVy@dN%a+k%0v%>U&t+7bQq)W(OY#or1)$ptE}g>U8egt|@oqf-)PGBcR3i3t zG_;m7rm(ZtmN@b z%Y&C!A$mNj0NMZ&tq%!N(u^Iw2V)VLJrMIQ!vRJ2JLn`s{lP;j>MqE;kQJS;{rS?M zm@yBkz^GP_Bj9*B&k3U8IVU-EPtosy{DPWlp)^MPrD%Ey%Wq>TFC!wRLE?ZRTYR@? zb?=G2y`@fSZr^e&tgLtPF)v>>LO^fWx)}@HLzX1QDw>-vNIvm&%?wt}twrC;>({S~ zI!>X0){|0Eg+urPznpM)*{>>fKMu<5_V~Oa`ZHipp#G-ZD5n6A0Jgd^KxYktpvCRm z==!;BD=RDDN`!$Inf)){hbbGVo&PvruK)x*ATe(n>_VZtfhNCwezIBZI`!BMijm6y zi;MDV1QM3eqU1FS22r!TTm<-5fq=X3>Hs&=Gkf1DHC93InTbJPCk(mf`=6U&@Fo0%~KR{rIo4-4>J zXrdfkT;>rNFryoLZiC7VQ#V+kPUi%yTc&H*E+L8|k`jgqZ1(%@UB!F%o~z|0ti_zR z8G4L|P#SrDe~j(`4{UpP*?y>4_Cq~r<7G5gQyL_tr5QljvgL=YTiHV`E!d09TXQ%Q z0bRcZm<~c19JwG7z<3mTZ?|%faBWy4#wNG*Gu3QzlE4Nt%!Z|-{n45sbMfh z5cHKS>U0ftizmr^_{(Ds9v%wsV(<=ht6V=86E2JC5Z9PNc?d52H=AQGfKY+_{rjY# ziQBnCq%&$L4ZK@$aUj_N;fa{hatGM?XNc1{KtfB)wcNhqDh`7fByf4nZU`t_msY8> zk1AeRAjBS^Fzrp-SOU^y{0c}$o*5(Mj~DXW$ zsCfbX^PeXVYpWQtB%sHod>*iJuA~#R{M7)(b2X_0sdNZ%e(5Ix&CtQY!CiPc7xp#4 zZf84?np$A5q|FZli%{NuOH3qGM9U0rga$Ca$l)FKE+pXsQKjsR!}lyYKjP$}9S-qx z6}r5XugiY-{yh*vbO_r3S$*Q*pa61BhUW~fyG|_y9CI=Z*fchCI1BO zMy(cv7Vs%~t_lj0NlQ!P5D?sPb1T&_&hNi>iM?9Jd=DZ14<4{6X)oJyEbTKx6*YtI z8wGMcL`l%;+NSf1>f*<)e0QRQMENQYdrKrPDBhzE_1p$;ki;4Srl3f$#lz^z?8jf; zji8|B7O{ll^*r5fTVBD$uW)WC#Q=$)FQvK0AtBjDhz52zr|N#Oz?F}rVk+Q;ogEM` zrQp^J7PRV`n(*0d0Ra+88i|eP3eCxYkNoA!7ZTVb+5b#AAz6X}vVp}OJ^ibDaOonj zQ-;s95u=O>tQiQiV}rW}kep+xD*W|p3Q&T6d_s$UUN{T=gSMDusqv*)FYGu$KKwi6 z+e96;3k_Z%s6j3rbZR;YcLG4VR~)hV5E}cZuM|!BIS;MvNpBx(v*w>ZH%ak0`Tu8V z+Klrb>mOtg5cy%V-iyie{qlHcxnse7?WsD*b`+-hac`S(-i>9}=vim3Bc)39d<3yV zfa0*ZM}OP+*_pfRbOo=<-F1KM5kiO6rH@$j?(A>7Bd9j)F`%i9*J)8q z`)2U+>sMOQ-~0=!>7F7R)L{1$vP!_vY61)Z(L+d0a=`Udc6 zHXvV?9~2Z6mr#H@-;78l0i8tPP#SK2UO{br-P>u*ww&n@|8T+z)D%oSAeRW_2)HarOzkPK>bv?OF?&dphj zL8nI=%DZ35Aa#N@dBdP0mRmq6uaD{abzBHeAbb_}khOmSsXGU5#nRemHda>Cy_J6W z4vBZsj9o-T1VSl+;48h+{nzET`zw4nI0?;5gB`*vFvT&%eSYhg+qXcr@9Gi#ke{WM z)xpyMSbB|hK%lewmc;{n1V~_&C{*EBNP;hR=gys5pS4rh*9ZQwfg46gQ@I81<@HSu zTV=MuT+q0GKM;D{tz1pq@9$xgl*?il`A@{2Z3-jCAI$_`11WvrSyg`xK!*e6>-6l5 zb+zR%I~MLg%v;2RKwM=dr8tbT@=1SM;LBjmH-OWEn1evs;Mre=m^{pT3V&?>Oc;X5 zu&q1YQTE+wXO}ZsUp@yKo~`-Oak>!`J`sn^F(EJrpoXbZ1LiZNvt69kUm*DBkz}FG z^)jm)Ngc?ILMSMT4~QH{8F-KXGkt>B^Hft2-x#mk=M(G#U{;83)>4;ZEzqxUWP-B? zaX-WjPT@)@`)eLUyiz?v*sAs_V*6w+pa@9dEX0`F;HQJdrG^<%fZ=a*1kA-LRIOJg zoQHwCubaYb2g^o&Q*bi^XgWeVA@FS$!2(HuAdp&Y$0{I_5NQ%oy>)OPLVK$jc(>E` z%w3gCX~Vsq)u?v!k>qv~JF`Zf1ugIaHLu(sl_TDH57!xlMCBqR(S zUD@AZTP7j{F%}S<10H9)#+`t-zn_qhkp+Qd!9#s*NZ(7fv$|pSpk=V!BGWb(9x7^ftjJjv;F) zh&96oQzFZ@s6$S~!}Ri`;DS#l*yn=s zm#4h&Lf(#=zSuziMa4kE>nG-DZf*|t91_qh&@V4E#+-oNmlzlrQ(!IIl0rrZf}gN2 z5?$@ptS#)>WJBkbIen|04`UM!oX%J-9!2RrD-P&iHk`t0dbc*RY z(#_IABQiCOZ6pk!onPWGDc$Z3d-q_o1#%IdMi7eBUL63r3r4n?_0IMI~Go2zU&unza=m1qT6+XmC|cDPRd9`;U!&B)v{d3^_dXY{%6vfnaR= zgLqk4S#T1}^M}ciO9uI0KX>&}ov#>Vz)B$X#uHdxj+R6T4i#_xDUuv%99#u)4Kf<8 zl@=;INz8(RUzNw911q7x>S_Sfh1Fb0TWh*05m20$MH zAQUmFJAvsJwPEmPh-@$m3qKsPQV+!(I>W@kFab;t9jyUyE)q4aHkh;}2J{4jx)FjP z!`HF|QK7)rqz@p}0C`>NPN(+|IGN1ZBpHF0B72$P>HxAr%F8Vkom*PkD88ciI-AI1 zTCnCv3!TbWki4;nuq2WhvI1p)9tidVh$-05&>QH*UBkgwn1wq~32@U|ihze_K)4>ECL#XG5Nc|BZI7UM&7SF2we|Q+P zNb(A78nvQ97sx*uC@6%zGfYkRHvpv^y$Yj+M_fDw{EtR)2y;Oy3JE|piW_-*dnft9 zm_WX(tgcQOT?xhoP8%hPM@p);!~amgJs|p)lp$?IWaJf|?kcc~GkiA0;3>7uQE59M zB@KgCF6ID82$D4d>mLQ(9x_R@5D4d^B3OGLTu}g*tde?Dm8!e5ySokawqSmJKrGM_ zuZoINL0ceYTg6^iEyhoMu~@U_b7oM~@n%0W`A_UW4Nb5_1MKHhBFg!2u?vaEeDK&ycKn>f4A|bhrTN){h?|EzYvHSbu z*TX-J5})~e-tY51=XqYWJ*=hFwo|I`m8rRs3G@!5`@_5@it|LsrlNQqlkzi8+)e#x zflY@52fF0_=v8S;L{!V;QaujOjf_7{YKYFWg=A^}A`GrT81DREgkd`nhNG~Whk+3M zpoEg!X4uTz`1k|DrvJak2uUt&1S}bQ9lB6ub}kSHm&4TOU4G%oC4Bo?jI_MsOfDa$6ki+;reXH3}pk4GY3>w%MAD)4CHR_En z0vA|V`d1&I|7bnj{*20(`ez9z&7l>5-0JkEwh-x^$OeuPt679o7a=isinZZBNPo7MvXcL9w3DV#cYR#M-)GVN2Nr57^0Eg zTJE~hV{ni_60A#FiO|OYTk9juo{KnxRVZ~bYt3tOie}H5QwBR~wQU*H!96BZ;!I(& zd!GchD@Xn#H^`E?(F{fhsBDtP;0PrSIo;RDvc*d51%s=p_rN;nFZ?Q9fbD>I5x~1h zY?MxfC=8?pKW*sIEVPIK1lB(JwRKSaLSCw7gZCTHDai9{NHsb=cjcQ@Y(6sh(}Hk!(vpl$(q#YcyQNVj+UyOB}C1c&mSxF7gX`D08PpO z=_1{qcpR#o_!q<*G*_M}fNLs_7?Q(au~>T(&fb?b@l1!ibgCy@u9?Do#}K znGH&rzlK8cl88@#=(g^8Ega;X;Q;1pN!@`tCtOy)U8j*v#3(!PTiU*`u@f}g$ zmXT^TPPUyW0rkYKGF#C7POXnLoL?P7EWi zhKqiQQix(tUPM7vTbWsbo5Bx>AKHNJH|ZVVEmKyJ)qm~$84(27P#WZ+l+~<9-+A?g zmr)%mSOnn<(@eGJOpDjw4jJ)Mu2CAy-kfm)T2G8EeA=_(f?VxZ>w&R#pwY1hA$xHK zf|v75jHD>uQBOl6`PC9Q_p5qNfF4DTIQ!)u((U#b0!4$hLI}1b;Dvn*XXQijAMJG; zj5G>#c$*Aw$cC(;lG-SGSM%jmo#^x(Xc%FQS{r6PY&l$}_sv1}-Me?P<13R?@Ds`Q ziyFL5$XPItijom^(G05gXQUEvx(MQf#4b)rSWBjOpB!MfQ>RZ`hl=!U((RINE$3#c zoT~tJr6e`a!wyM&Mr!!Y!4UGKr=?Z2S&HnQ!rT_#giH{G1#D~FH zVA=d&4|-E$#APQw*|xhcNW}vi6e=gdAt6sds=Z3qoq7orA9e`z59XXm_ReoG180Zd zVGp|mpVTU;Manj#nxnNBa}$pHi#{wdni9Mfn4Z!{uoD5dV+65h=I6(SUcDNVVF@2L zl4%&9ZHP=3>>Ps3PsmO3ac>Xc9A=JY1_D`!oP`QW{^*pNJ31T->&YR|EXY(7v2~?YjiL+$sXB15k;C7+fr zz_RXD-&@LlFWXh^dC|AJ4JKj}x`WPFC-_3-5;m^6r9~CcEMfleLl+J>M)D&%G{A1% z#VwCwAsV^l_9Z>!wl+aePfzQ`q03qq=}CMI2 z_Sp&V(NvA@&lg@FjoieGZIv814?BOrJIE!eX_m|f&TY#W{@HzAT-OFQc$F)L&DM$iK4IisvT&x^=8_v``wC;yx(bnP zJ+~IRHI}cT0rSKLJY|&CS_{tBDpp5cm!wBA*WucGjLX>0#ovzP+IsZtFTur&$n1oj zjD6qAl%lOB@$GRIc>W}1LR)u5r;lbyEy&5< zdY*$;k{+AVT1gdzK_yQv&Kw>|m}=&BHNLz&i4g_06SlT` z`<2>r<@gm$bzbvA9{`JA0ag4xlfzSF6e@`13Wt)oiPJ&kMnDxSaA0+DSoN;{nO@WL z_RBhV_AT+{K2dmIq!PMm^aUgNQ6t>mIulIgnwo5#x_tAd3|#LwOloKjt*#wsIco2^ zg|mr*oTu|e98ZWi7JpDDvsl(l^T&^QZ_LI9r}$0;98?;tYG~=AadXs1uT#SwY_iq! zseG^50E-Jy!s@uy`)ZnQ!ZIi;+X0c2wbR3JdV6}2bTAE>#Vbee`MHTXGlTPY`dS@x zxl{1Dv{;YpjfNCqE-;z^b(`QUWrW8Vv+)p472`YC1@4?LF6`0!r%V{x1C~Z_6vQi(a{o`_)<@1Kilk@^J zj$>I}_#}M30l(~saGgQXe=1;GPf=E^SP^xnZf5%uZ4Zr_5O1&mZ|dsbsgUAO*m0GHtR$vAxB zK6%k%!`<3f^@O{2FCq{NbWGy6oLc}^Nj^hL$0SLE zk!Q$yee+o}&7QvGQLw){pFQSzQp&7RGNs&1$y#wbv?1LQSogo^`jQ+8z7`qqWnyeB z0KXhhKJmNY{zOe`LSkx*`)2|MpPmGi6W;ntuvB;RXfvmDY1ZWFZ8Ref&?MkSZ`6yr z!_h!f1{g`ewN-{5O|_g2C}z)**U<2kxQiw;UV=s-wW=ZY zu1}v3#c1*)sX%W$6f9 z;P(8k+fNA}hN@!QoUf$rjJ*<~yLf7HkW?Wt?q$XGiXos#9gN}$S;V!->VJcqhofVn zA5MIbXR0W#=5&G<2hG0&HO?%>W7$9NjZu685Ds}Nr_(9xtIePN!R)&InK{D9nM7yL z)<@GH49X>UU-1Mrni&2W6ozEg7eTv|)Bz`J>L^Y9k5@WkuUlP`hBa@zvVXAJ==j;Q zSwneOMh=8X>Z(M0z3AgnW3bmhQf_2f4rbR{RKXR>$EmKuXQFZ)Ygex?n5HP-qd2-m z{|?{f_nVroa$hl0YIfbTaSG$u!CGZ}s{iwiQ44!}`-1zFTqU+TH1nhORWnN)-mjUGiu*A% zrs<-6z()c#&Qu$Xj(F~OWMl68qne?a+TsjgLi4b~ml|J8S8B2D%jWIR>~c3fX_TLz z53GmVC@6VH#3}wt^0Ldxyo_)RjHEGBtFrGeWiRdR(VD;4=NCGwyrF;B)YDwSz3&2( zdBHqHool-8St#}R%m1ZC=vy*>r(4a%k4xKe;mx=Dp+HgVV*Lieon@TdZT(L*P3qm9 zx!Vk?N~pmOIBEPR-(*HFMj7Ih=K>Yq%K0`@x`Ptqx>r(%5Ajr|B+Rfm#^!u%brGJR z+0hS5Irtlp-qG7jY}?SxHD}aEN#Z?ba6-}W23tfOZ!ZDzVf_7;c|bAp_HE^Jdf)Po zY|^PNPJVHUl<0T!Gr_w6XLT4%^XoOHXO=*91bV4tnx7YsO>t5yl z^7+UEt|92m!1PEQzSCPt#$|CU$QaT#d{^R?Dgw!ORL^$UWEJ1AO1 zzqVWzeJ6u2WRiB6lkb}PGFi-dk*~^?W!Kd<6*W@YRXvjrhG31^CAJGVZLEKKvFcYT z47D>oMfsQR`uR2LIn4#`RrdWUEa*!S|3CJ}AHVd)0?XllMhbSe2A=XyDVJ<=iN5}+ z)#YR^KMXz-dW|9ER8!z4LI3~}k!`zn1rJHh5Eiz1{pS%Z@*YQ>7?>t9RM>nZ{nrOE${SRxGVC;AGC^KVL&-W$z}>7&A>!kNi8k;iy>W$@#)7jIQ33(nL6 zDeWM&=oLB-D-|&h{j8dk&YQbJ-IIm8Uv^&M_&YY~Ph1pfnrt2sDBPKP5!G*Z+Uau5 zWfy$DmdeZZ%v4eISKeHqC&X5h$iTD{?Dpl3o6B)YLw-L&Kt;xfN%8EyhdVx>@MD<~ z3Kx8Txj<`7#SeS-JaWkj$DGSi&gG7Eb)qF$`MCa+<-;al4%0-JZHkkviyk1o*#Zs}mt;gBet%~(6_5-x_DyZd&$X7KvP#+3`FW7E^mpwyW| zhb#-52M2xG25ke3aRX{y&eBMV?GAP#TTEg6O`Br450iZ5upRODaG1xg*8SAMgZ*8L zN#)c}@`+Iu>Amw)Gcy|eR*98VB41cTCWt2+-=L%z_du}IA zeb$znJiJ$gWzzq1V>sJWbMrvMw45BdfCm4nmoHx)L-pnwcN(xgpk2n#sNsTv2)l#9 zTnIP*SV?Jkb^G$0E25&JThzB=4HyR^@X3kppUKY7HYx093Kh3q^@8iGxgw{ih!x%B z-l_WX2A!Kap|ig~!3k$xOI8xp>C>k#6L^&AW$X2Pdz$??UAvLEBuu6no%bFkLHR;| zVfT;d>d{y5YSeb7eY4j)NeZ)t@R}%xS;g$SUg}#J8`9giZ+}ss|I#~;LitvsB}}N* z)z^22J_`y8GDv7x+>A?3_QDCj#vgb8{{5~z)2A(YHWwtXF@#{lD@L03YBU#eMv8Gw zr_F(vcydWW`vj`#8tCw-2O}CB`;FY2CZ8TkrO46g>FG(Uso{y^xLR0QjSiJNGhH~% z6y69EaB6C5hz(u5ad2#MvciBha|30vGA8m)JpRM7fk6Eg&5H$*FE`?vXm=YYn_xl) z1_#F$7e}r;5)#iW!<;8vw&pb9h{R@{cC_K_*5N*sRidA|RcF6;QHu@v0Hz3?^JUDo z(OPDQjs3%V`M30I4yF4#w&y7*(OKGpwFG27RNj)>TNb*zb={vzH{nL1%t$TsOl3eV zBWur%5v6@$Jk*ee*aUa9IrD|nwvRgEDg*j;ecW{!=pUS-IAuThe&4x|R+Q88oSlas z3GXgm{+U2)!nd>g8AA^93>(KUIu?C7EN!SUh2Ok-SbA=YG5X=4&;(8CAYNv- zS40Hq*w~nQwa=wFd$m1oznKz0y+T)Ue@b>zT+4dWkJiPi9fIfXcNwq}K45(EUZ{A$ zM|D@zG&???`oigxjr(IQ-ULm@L*~RTcZZxhtm4=DTtIN=4h7x&{Vqdxx?e9R8G8lAq4vx;xtuqQ2;NGW2Uwh!7AH z6aVP!#8A|+i`F!~T{`Id{kx<=Z;m(K$MaNC=+~P=_=_0vEQ(bls&iH7(I2>`MN4T_ zy*Y2aTt&1@$%hZeW}lB*nuTP3H1>%W4(1YE9UlmUk=QpkAxB4Z0G^L^Xqr#lf_@ zlgyl)4QvvkT<%YEdz;(aKPtv^Dk>|ke#*|iO_ypMi!Gel;H`Y`^QO#-MIBK^wtlC{ z`plz^s@T2HRFrS2#DXu=&|tiH@j{`*_D(Q^${Tp+3!}pA1B;@9d_M^yzc;b33l|Eo zaoy1_UAmNzoGd_lt|d7nF6)`0VLRn%F40~Hfc>|v)<#s*h}>~6X`}_6#U4pH#xkkt z|L6p-->SY;?RNI3Eor{aRF!Z!Y8o2F(0A|rXsD^jlH}9sp{_hAm#7#VeR;vdP$WxSw(C6$rE z%qm1FLeOW#_U6r-FQ%j4J}m!CBj@Uv3hC=1O~DJ(mG9z3e~42}%NW@M$I>_@B_&7d zg6Q5wM2K(cd-y#}QOp#~RO8ht9gUtXRu!JJybD=rRz)F2uC1-@eMt$~JC6SR!a@=Z zJTjMZb;oW4w?=KxyMq}oR<(bPx?Q#s8P=?^0oWN0;*tzMcBi(SRbLdrbN^OdZ3@!> zvTCw&zU(SDUutJf4JI-atE=e--OTigE1w24MUBH89=0Zh<8+%pFBkWSecjR`o0Xf( z*fpM(Se@y(R4ceoo0NK2vBWli!p^1d^>}?qrkz-KC%z63W$g=2GWN*t=;7w~Jai65 z@J6iD+I{OnDq22@-8RI^KO+{x&`wDEaS2dU}p34O!Uujy+f8Bd(Gg0SJF%OdLG-cTS-dm^)&G`Bh~zKlxAvuPsP5a+h!BwCx=&P|0%(}l zS>N+I7Bjr@o5sw#&00cdZ?k?heQHNr+X?6L_xaJv1u`RwD1u96GiW?Ag#v(80I}@s z?r!75UuR%|O-BW}1O0b)Y|ar8WoG_Ie|kWP2jq*6f`) zbp*SqQ$Js|Mta$>$p=z-{b$c!wN5u|QJsg}jla&=sHuj!m2JOoGuM}YR>+r3%VBb= zIj*a~f)3X2)&y3S#?8EbqlXV4zE4aPIs0-hz4{A81&K?cYHJ%@>m~VJICyw*U%vSD z-zR=xmBm0y>v$P6EXM`_lh38QZYwL#xld5O{zH~>9J#c`rnkE>kLg}9wYVtc;K1{B zn5ks#Bja+Tzs+X96~Jy8Ik|7{?_y#o=DIV5T6dr6>+{>$ak;sT!QsZXh zu88*3ym4mwVx!RR=3-~0*+nw4iE!$V|A4$L^lu~SQYv3U8te2uGoO&6ae;-i`K?VgfFesGd^vNmteQwW9KBp z^Afx|==I@ZX*5;O;F^Yw#p>HyO{bPYjiy>dTx-MLKi}^kBt~-p3 z?I_7$S)4ETo9M&6Np`CR(kpLkye1T2a;US0-(+X6fp3n_O;cIqW{ZANtlD^+S=2W! zKK>-!rDfrzcaN8FK5vJ>G_cfutffUoa(#7opO%j9X@xeFZu6FL2?>}aY)0b5@^}^3 zs>Yv}k3Xk4cS=k1I|M9|sm{`a+Z*$}?mAH~PWtj3up1Sx%bh!a{t4v6txTTXTbu`5 zqwLSeFv(two!Q&zES(rkt=DCV{rveW5H4l=!Ka&IOFd45q@8#?J$riU1 zLV}(ipM}Nkjx;s6{$*cw^C^7fV%2BDP_RrNCCLpt<8hb0y($DrAbRCH8LqpGjLa(l zBEE13?N0_v>`;zTQDhJ0<ja2gvMyE3$}qwF>mIm$0P z^TpsJhyfDORW>#vxCgOd`ex40*dz3B-`m??CAcKiE%}dn!>*jcLBfNko{~d7m2FwM z(9%1l`c^>YSr37whFeW#^OhC5EE*ab#{qGDjpBNVLRI^cyZ6ou8W}NYq+h_j#NlEL zGlQ0vc8KjhA-ly$ZEbD2Kb08mvNFxMdplo=Ck9UT4b+}7#=-jf<7~b2P`ST)@JaH? z^XCNn`}-FzU8>qypG}9bs_F>?<27>vqtIE5!^DbGrphn$_=zLO*e z)QtqSjg9wVES<_PZ!GkCsvWF^Sg$n;Jz*h+*YZ@H??_1L9u@K{b*9%dGkRka6D#4s z9^gQ=w6^**>NQ*2H@w1Y6$X3Ky)eV&(o`c?q)8|ePr35tSubCKSP+kseXYW9$gOkY zd4jhlTNspB9^c|0h;WK#3?omLiItT#?hYBB?8k;>1SGMsS@rDsa9~m3c+fPP3NZV+ z^ ziUE=ZK3@$fR5Y48VRab|gxXN3AJsHy8T6Tj4;Oo~#n=>u{axJLPOh!5^L8i>(kLo7 zLWP@|dA2vlaFqWihtiVpYj!AW`)X>Gdv{@ngE|0T6O#5$B!YU z-Le-!N3LEZZg}{~IYPpWLgA+~J{{=j==djiTjhKQ7pv2sR!gg@es^~~VVc&79o>Wx zQvWfr>4Ye!3qCW(Ult5iZVR#=bovKbIXT)@uGzrlz(|COQ$yXtnj4_|o$Ap{Ro@BT zdxnN7)S*;?pIxN%1aIfM4w&e?Y5t8r`WzvA3uC^BCR>BiE)kdVw3gKE35)+?z7An#cn*W=eL8w5knY_cp zIxZ;2+(5=_U`JY~mA{B!07by2Fere4`%>F znN3Qvp3a58T`Has_Gaqf+1S`9kQDZRpLjnrJKNmR5#Ox}cmrqrj6XW=@=yI*qvDyO-W;8M#xyiBqXmAT}S(jtoqh1fMb=6U@td{ zd77>;WWp}%^9%F)eain${yh(ON(eO=BK{`GQ*W17tK!*j<%!A9SA0;io?=Wv;GtgO zhO^gu_Hm)*4arE3s_&1nPaF@Mwb{z69t~v`T4i%sWuv#BX}i|1Dj_0*75VU9#D1-6|h$S_sWTjgRT{{#jD>;^t^q`cqm)#!3ErPI;ZPu7G0e$6MNTj#H8O|DfSs z#)4vcG`DpBMwHFWHO{@Iimjf`lK5+YwX0#}?LQNtXoaO5Wj%t$k?5#d`IB=#BE3Zt zCrzMghXL&Rp>o~ynOgR-CGp~;TTqZ|8<16|ib*^t_GV?_}DW5EFZi7g}?0RfY4q;mH1~CA6 zBycqH8N%#MEnMK!*H4Q7MBv*w3*j7nXJ^MeL`u3kMQ%3BkWMG7O3BtJRR#&L|4xnx zUg9FdgD)~*4WA%zF^@qw{mhypruxhgFAn(tS)~0&81aO*&UyzQi;5!FRsW3~!^MA; zcs+klkbEI&d;I4dW9nYaYCPceE0QJoEJoNQ$Wk4kMc^&bN{Ux2$5MUkC9pito?Ywd z?X{RRCOrNZj5JL%!nv$P4eymITQ5&r?O%*F4g z1VRZb^N90C?vthde7IU_)_sk?TDU)gaq*MVY{^- zNf0~}iuP-4@IUb%#0H?{iT^3$ynD?49ZDBKt;QwW)PtnIpsCy+>Hm9Zijr!wDZ07> zkLNTYrTH2QVuofo9NPEa2?2yw@=SK-4ryV(57cRmq91EV>cV(ZQc@I6 zpWL7#BM70dpPHK!c=6&6U>TF$`P@+xYN?qQP)FE{4OfBe8Fzd{-JcdBBD zQY+*2Zvz6*Ku1e+*q=>EO5#^hxdiN^QQ`oBeEkcBP9YyGzqj4#W;y735p^ z6xgB=86hs;4aY&9Jb4l@p?db?+lHg*k5d#fwQ)lWyg*Eh6jm(ry*)j;?7km@{scV#M6kv%|3a`DQ2&l#HC<{^0`|M^Drw{g;4oSmV4ZqeimU>Bqvkq@9 zj{=3jMC=WwiwV*yet4q<+ZTDiTT2r4Xo)ys|rMqqt?y{t`I0R{<| zj1v>My3Fp=;f-!SKDhP|%G&lM?CrS$Vd>+cXr!WCYBfcPn*@(;qtFru_|mEyxqVKM zx#W`N=)43+0cAqQ5ST;BUl1+LSJb>jGi3l|Xhvo+zO=?!`68P^9_Hv+uc>v3@iQbIT($HV|E znAMJnAI!Iwo&@V6yh-EBb|9`6idH3A*w|*NsriH_fG`%elaA61v^fxXk?J-5d3G(h zBy$uO* zkBEqPCZ@`W5b$|!EH~^VGQxS~9KzpviDk*z9%YHTQPBRref!45%^h{#!=0WUSZz2X zzp5(Pb2BrGvv|=46U@t$96rJm&C(!Y7Yp5jD z^rjbi4@-3k%=I#y-RsR}7Z{6=ebVP;aL8s}Pd- z0+GYfsQbZH@DNN2w|Myt|CpZ?(j>2`riElfs%H)Nu4)szFeQ_g8`sILsGO3Rh;`DL z*Ni9MJPrW`X7AI}-{Lsb|Nm3w|2Z*nH;En9%evOq7hGLk=NMYv6~tNa@*YznraS{d z=4rK03_uaQV_1ml#vP5v5F+*<8tbT@#hn{0RkQl8Wo`Y=I4sZxx7sK-E-A?qr~e~? ze8(QBc8zZ`_m9X6dgf4Za3&ZS(KJVheQv9##dLD)>3J-{EJnCEKaY+w7%WlA>=!?R zMP@Y`>F=|%&%<{?QTyS8i!t-nx{Z-WtYuRz^oO~K=Xt-)c;%Nnf|03^^^tGfje=sQFNv1ZB5gvhLrtNs)m_D zzhmsU0L;{0fdni0$*i3ElC&?)F6GWgK`t`?lwaz2WER$4#yq}mJ>l`thEqBP|Fb=; zs{bWG#vBXUo1vkh?d_hPp00J=>G*?Q_z}V%RKT{G&!8IEnCo^1+MZhgvzZqr*(Ct_ z&JgpOb;tN!{73|#ykX(sc!N;7Kn=LIP7461$GtU#W((0SAvM*lb-Hq(_~kONkm}$) zakxw2BF^vOUTJZ#_X6R2K?twJW-M|9?Vj|`^Aoe3Y1P0anvT_+0hMLMl}Pp8lP45p z4tu5%JPuKV4Hm5=K1pe5LJ+G+24<$G%ONHM$~j%wpL%iOO_c^*IV}T&ps8uPHf9>c zFg&g`d}W5ttj%Nhq@?gj^d982c6VRgG)`P!TYI0EcY%wG%l0+>alnw^J331nII?b| zNFsCYNoKc#c(KbXvUQugHuC{h?O|bI>P#0{HUq@ipfpb!6dn%xa;B$d3eSHlhn|)?@lF{6a6N)gP12(fa`Wz1T|24tz8{z}R zqVExR&}7ctt{p-OH-K48OiYfDtGfT69^?)286^;hu!3$`~haAyrEOj+B zO+n%MZ|KG;7||`DV!I6Qevjty9T-sUk6n9?R2=|0bbCTfIV~(K08NC+%F9=eSoK>F zp@yNrb#*9|VB8r<-`3+n z@?9HN3w@!oUu8(yO&s@Ab{9*@n{^-FDq;spWzlZ&rS-5Yk#?3!M&8=52CSdh{WoR} zg{;2-?+e(u$lufBu|z_5i38l|s|uujoLe4MSqBF@*G?(S&dwjZlS>X_hm7P0{BjDPzfp)H_=d#Ki#3Aoej2_?Kt+}?p`(M2YDXD zHU`}p=*GqCg!Y?-gP`X3+3(KVo~0)AOuwIk@ISW0*lJ~=w{%#zKId~hFa&~v-FoRV z%mQ5_cNFUH@w39pYTI@4OD$rI!!Tdbsi~>Am~P#?`3jk@*3%zDmV(l3UGWC}5D54n zdgmN2DZ68eQf@{JgZMhLJurM3oggHl$Gi0bt_OWeQH2A!Oyp_MZqq;i`$Yv{pb9+u zB{Z=406?nZiYx$W2b4~pt#UktMIF|DAl88J!~3FDPbjeuX+GVkpMy29qrKgg-yOGH zm*uN2%Lwo?z{s^k6ft#TJpmO@*T_f^X5lvm7pm^6|Bs}@gM4n@2vaRDVY$2Y2y*~K z5sF2ucl8%<>R*aJeu`j&A;rbG`-<=1f`O6GuGcdwy^{dDT%;s8<^Z1RvYbM7W$T9+ zW%yBIfrL3VJL{aBSt6B@7Y0g%jt)(ZVedEhpXA5~nSX*ttqwp4rdT?t$2b!3h-*!Vj7q3vjXe2t;a`r zBds$jUr=z`6ud@d;F~bYMSFl> z9v*V-%+PEM#{e3subRwM-a1zScuZyT&modjxuv6axgB%m$NO%X5IqPY8W##1Us)RKo zM0!{LK_)Kt;*kJQw7QrtmIgKsQ` zaEG`pQm3zfZ$q$ZK>;yPRE&T_ z9TU}TbNekxKok4)Z1XEN<50IwbQRDOWY$B+;0dWiQY?GO_&V)stxAdQMJcZJbKKjt zQX@%f``1r*=C7ImJ~IBJJg?gb^02bFbQnRed@|I2Ml(o2zv`2}^_EK;?~(`wuf zZQ#fT_ZO^|K{^9Ag_7T6a;HIiL=hea==6T!;Ys1vTbj2*e%0NDm4Pl5g2fQ!aPR_L zdZWYc0>_dGkbu{F|)V5YQ4YSiSQr*`uT#j_BL`$+m+cNz^gj!uRo(XHI)xG zt>sbj!*`MCmerT65ZcE;QU|Ql08_pJKWIK`(~+v;$!Iq%W-h06igwyhJnl{ueSoe3 zN52{8y8_2Gn?b(K1^(ix9P5)?VaRN8Y z3%LMr@%e?mC&Tm5he-ts7?wsms>l~tpjH8gOlFw*>tIR| z_yB$W^{UzR4Axj$XjVvnXM=^tHM4HH)urh*FL0JXi4Fx1N z@|X|T)efsh!0iiE=vIRcH@}Du8F(n~P(`vJUWYh*a5uPi1J-DrcBvS4q_3Z2X#Y(E z#xXlPJ3ot#O%XzQa1sH(T?x5wOZsuMv{JALi-4a;3@b=I{Dz0olp>HaiA2T3EEey< zpvWjGc|ym5_dZFnDkF%`-~DWQspTxCx@^ODNc3Ot*$ozbxOQHZP?)Q zJ8mQ-{wF!2ASLbnQ^WwP9{7*kO3pUse-JJ9a=MI}kdo3)nW?!9brY%#mh0`_#&bvd zj{9Gc;c34J5adyWzZk{Lj^qDyZ~T34@LzURV20jTO_MkC_G%gZD}^eu89F#>-Ri*O z2L)Nzmr$4#h5fYGuYdjKO%m{JyIoRC(e3xp5G0uUU65GKd*5BWc z)FE=yP zFcq_4URMmO(@4|)t@Tsm70Kg3CdIjYqGTl~O&!9%?z3n43u6z|)O;bK$p!8z0)zpB zBnCe}|DMu>xRjLd#9+oxS3}7~ifjL6Ip0vTy*k<4)%6-#xQPF6_<8;pz4p%+X`=sN zPOYyAfrZJ1D8WTLGf8uU&xgv6K~cXVktPNiQ0#N&lbl?kmQVlMi}Yub^2m$i&ur1M zU0=E?{B%%RefX0g37G@xU;Xr5to%LV? zhz%s8NGS0cwfzSoI6?7;I7qSg!MX^BF>i?Wx*9eEcAF~Tvj_|dT8_yB0w3XvDDD)$ zvw5BT=@SMt5+Nkg8&A*X*4DV5ndpI+piw~m3iYU-hMp*%#G)~+Ln&mFY=C$M@4f(| z22uu)%^iCrTZTE=+5JB@+A4zKJn0GsGip-IPYw_E3(Ob*qT9B9XftDng`}dQVlc%J zl$S9frLV6qr>p>cE@cqyG%ax8KyN|C5SG|`u$24kPqpdAsYQS_ETv&|9Z;;|b zX?GkHA%hEu1I8# za`fSLbl9DgP=hoWte+qf4lNknrR4f;^Vy$lw7=;*^K+3E;XwTu9P~vdCE_1}xj|k+ zVT)J$)Bbs6Y(a1hG*Z#$z%3W;Z}iUXE9DrJt623{sW!ENlg222oDjMH=1D7PU1-ey>?oe>2COghp7G`QcVMlmCK!HfFSf2Sb0eK5ppWUlR z%U_{ke1YW6&Dkiy)*rYg_HZ5y$cQ}HZ#CHH=Knb<2^=`HrU~w$Ft*zgmDw6qr{J-I z5%?9}&BdZsTzW#!2~W)$I_TgP-gr{x z+;(o$9Z^n!PEcP|t%uRU5I%Ic7k%g)C*%wM&1hrR(GO@Suugz;`dai&%T@_CV4}8; zlL*SbIbweWeo>3$)PVXkzQXX){li++TA$5qN*LuQI0(yqiU4sNfxE6?iAJfR5>_rC z?Ii@Sz7-;i84IBJA9GUZ|Cp27D@;U9e{DTEBJItg+PDH$6Zo9K###p6l}}XBvmzYQ zI6;r(f1Yq^zJrT!Nm^Us($yY1$hFJXf%mA~%?MlX{C@ zWGX*+aJ93&J-usxbCA*3$LI4wMhQfQ#*OyH(ZdoBRt}EqgFtT24PLF!;ACf~4S^F8 zF(|*=u>aUUH1xg*I(iyQ?MzIT3UWRjIJ`d~nSTBsuw^-CPwtk>Wj-2$+VgW7`HiYG1#S20hQE2=y0bS}df zw#&6;%}@ahacTm*Jm@Tov>Kt|*~U5;CO>#Z1-wzPIyBcA1c_v9K^1w6_ovI6ImntR z$QBp|ki@r+eA+MywiCCahxs+%f|jiP6+|1Vs25j)D$(w-EsIM^YCs7EEo>#JmHfh2 zK;f;7A8LIga(0q}0z|>i_$k$X2O2 ze?`OpKjuXK9_BiXD4)W_L4kpnFPzTE>_(}ptE1iupO8y>)XGW*EBv;8$5Oi&2LtAD z;HxYb2O8ZDz#(>I5+f0i85`uD{HdL;{E3=HK?@)1KW(N!TvNYqcrdsx^S{r={;M|T zKbpoa%KU_|64M~b0U-mvjaMKVqV54$Bq5>690f8zjQpm{hj3o}6Fq2?h?Mzzz@8af zjlkeuqe2`|7)SYuL58#jlM^_KT>zY7kXfUkXz$8;c6KoEgF2MBH*Va>LyGP8G<%B< zn+v~RQ0wNw^xLh*eda)sTgJuYK!N@Ga!_Rj4e9vJUbi0FWzFxeKEo8{e1gqE2cAvIREnmhjOMLJNY4Iu%;R8nr((wZbMDchb)BrbOI|9V>WNXGJ91JmQA_W+fq1NaF z7LX9X6DYvJz{5t``Z?vZ*E;S^t3HDc?8tjD=YHFjM|JwIyYeVjgPV0L!L|&!QQI>1 zmiqtNyxG}**)z9Cb^d=R)lzxZAbA-ys@lVyw8QIa z(0+rbmJ4aP4z|evmNo_vknRwB*ZEV{rYne-K<4ITWu^A@_06=i(9m$2ubA1l$pMqg z#A6oXpj^XVYBpBZ6$-^*t^D+KnSmU`a8i)nA}?bi0?`=Kjod1S=t2f8#G^UhL=GV0 zje#ep2EGlP9hR_lgf$1aTm9}+{-k=^T1A}qcQe?@CV zp*tQ1)s|9I25jxWbtwJ;yAb^EHLEpU`SJtL++T%o_dxr1t~a;H31etq>F@V;#=!fk z&QxZ=TA`g86Bp+^c#i3|L%?5nL2h{ZX%X~)SJ{`j*3|Ah^OeyX*n?LU}`>* z3BHfC(nF#5%E#m4Y0Gze7uTIp^-A|%T)B|SrQIh~2p^v-r^P{9C zkRhE)C~I&6v@Sx=A~!U?w&sBd#mbM(!^reP6B3`KakR1i;Lm01;;_4Gz zq)7DFx(F^(P))xlSnF)C$R1?EX zbwnnL=K7w;$+`&Nf`ouTn{XQksl{~-u-y_h>|Hq2YN9!A;Uw+v;jbI`wQ0IijD3b+ zaj`L2v-(UeJ+WSR^~j|J4_p%qdKwz{#%%iKK9;@!r7$ zR>bcI$w6WtG5O}a(Kj`{iE!7zkW0NRW&RYm_PlMExU^|`H|BBC&bH*y79EWarO;CU zcN)~_nfA()xtG=v%TiD^bTn^#{2F3?^JA2#We6BPFp=tfdBl_P_=Ae1nWi7=Oz(?| zNTIU>I`Tk`0{bk}%TgPjnAQ&g`p{YJ#X*am2_16(*n6j2<+Ig%&&P0jN)bMOel%dR zFV7|~2GFO1BHi5G?P1uPbF@*;ttLti$L)7J*(+N3Y4nO2nmza)Hd8L-g_FIqwFfKv ziw@)@tOjM!xc0?nUGKt(ZSb;N!&=YG`Qm-4#q7tiU3{&*y-3sGw{L>#dc*9wy_c-) zF8$n?=Zn%5RQBwoK7pfp03d))xLB%o6=1sL9rbNARh1@(YfBb3_ZREk4_jnPUK1*X zrX9}n>@@qrif>#{Eu!QlkkRnyN$?!7uUho1(_bIe_+?L@jXUapx3doWw8OnswUf1P zR;WI5b|$sb?O7&hTFGqStm|N+4i6R&eZV6!3BU#dY?;YkS`$y}Q(bXV)Pn z>W^K~M;ieJ-FA4aq?9@G0b7)F74{`jP)V~|N}ApN>X5(WA-Er5oCI4;6jKdMZZsY4 zH9?~`R79|CL)VulXn+TR;)$QfwsEcQoXzHS+S#syJy5{@mLDl##*iq>I6;khTu)#B zb}hYP5m0`pFLt|@jh44uVc&@|^1Qurva~6?i-~HpT%G!2S_kJ%_zh>?J<+?Fj+l1X zUvAKYbvM$*a1@@9%;Gwq&i~y1_Y-x)jszH-hpz8!UsNWImMUy9UbKj)+oPM==ToUJ zRsBjuYjM{;dRVN;?k(!ypg@|c|7iVg;;bUCSyo-ea43SIN+92!v>nd9Pqm93Pw++- zX_lMoFC+rg1wo-4fsB!hwipikoethe>u&3Yr!`gcK}g-KYuTSREc)9X#6N6Vg!CB_ z;vcBX^Q<(ryB^98pY`6!SIroHie22$c{mXqOqi@%ObpvLRp*;cLf-^1xYvtT>gZtm zqpJvh1m^ED@F1X?Bg+IVHSSa#yXd8O7f0swZG5pKf6^0&j6Zq%KWus=j-%gWz-n%8 zz7&2ue!>{o*(a>wiZ4;@FIFhUsUNh!1{_KgnxUZsGtP%wZD~Q19%Sn?=R9(X-yzgC zs9mE;L?^iKB&e-oQ3g@QZ5~*s>9mUb#u>l{VW8c>eh($;A*J!KuSM#l<1i0j@z|L~ znKXvx4Ot7W#ZblxrIGw7M(YDE+bhk`d`z}IX_KbYyG|<99Sas)lmgx}irAmWHt%Ad zr3%)x*jp8_@NBjf(SJAgMHgl~vt+SMfHUahXFWni$Q`qk zHroES${jd{2|d8J51nIgto&x}t}Uri+p5I!P4FDt@|IugnKcxWDzeG2 b-sj1vICnfMIcos6fkTPhmlR0lQ+N759?X<8 literal 0 HcmV?d00001 diff --git a/blazor/spreadsheet/images/cut-copy.png b/blazor/spreadsheet/images/cut-copy.png new file mode 100644 index 0000000000000000000000000000000000000000..b06b8c0e2fb6341872e127b22afedc05fbddfb5d GIT binary patch literal 23785 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 literal 0 HcmV?d00001 diff --git a/blazor/spreadsheet/images/paste.png b/blazor/spreadsheet/images/paste.png new file mode 100644 index 0000000000000000000000000000000000000000..4308a6e0cb3d501c6a3ead948c5ebc1da72c1063 GIT binary patch literal 24188 zcmb@t1yo#3ur3P0g9d_I2uTR;Zoz`PySuwXf(IusI81N|8r%sCI>_Me?(Q&fC;89+ z&Ux#~I&ZxTYi9TC-QBybx~jjg>YI{+B<4$!mvC@!n9@?>DsXTwQeo*kRAkt9FtP+C z>;mtqA}I=2F+#Qn`+;aFA}<05_bU$l(HIH#8_h{d+Z7HD3-sp$-{)9t1_x*GN?Ke* z&CB3u$#6U|GyPcJIwvam1wL&*gHjSEUB3!qPw+;>%g8Ql_*cAr{+~XniDO41 z2uAMw_(&QhGbdG2j$y8?A#458jho!1+-D5SG;qJO;bbZ zRjFR)cbIPi1`t2URkboM7uii|ag=4-D?<8ib(At|-fKRCM;}?D&}uaElr{dePxD9b z7c`u!b*}G;iSiAeC@Fkp||;Ws8Ig=kMRKINQS zX0?&TSWEF|_Yer@-8m1%y@HrTJsS#PPd^|G$J+YH9k^>Q15W~Qh03* zj4}CrpI}!iuv|~5cs^N|dEvc^x9+Qfm8h^UwOx2a7yLbJiqh_#*Z3CIBoW=9<#X`u zaqrr06Nch*H=C2*tdz|bYf%ia_nbR?!;vgD%Z3MBXX@2X8cbtAAq0Fq)SJQ>euxc4 zhA3Tn{r}&9BTNej1 z<%t129p3C{Tr7Ve3JBa%e=;U`zGVz+0_@lwSGfsk<6~zwp z;;w58tl>ogIUCQf@F!}h(>jjIG2%(CpOVoC*XMMJ$2qO{Zaq)liyeugIwzKL8tH^J z%=_-u_c^@T@7cTLCcwxXv75e7MYuMh+xbTF!f=^dI|1tHips0US-G8W zDLZu6e(`I=Y|@;vXM5JYLit1{J}-8zaRYOx^G>**_OMMZ{mB^-B-w3^^VZBA?j@%v z8o)dJV*;~(%VE88B#7i+)^uMs>XV+J6LZI4&H6f$M@()~9JM$1YJ8%yEWCV&qvkFr z%+yc_l8UK{@@hi$uFS5aTGP7=@q-^6Y!bBYE{I*R%WP~qn|~z#{g@}odqq1!<76YL+Y z;B@=ZF4b(=_Wm`g9DFS+606UXo=HF{hJA0&QSIa)XsLIhT1=Co-mc#zLD8H?PWF9` zHc|3He-J8GJ%)Q78unSAaJNS37(@7>Ft1b72aA1|59i+iITv9@dYkMiYj&H06Y=gZ zO9)p-*=lTIivcS^;hy)68Al#JDT0r{8Oo5blU|{;Y&bgUUHF{s7G(w-J%SsLac_JF zbN1zN8_`nDc`&%Cts76Q63oIJg0sG@Zu`58Qp}3<*HAV0SnYl5uUZGi$uUr-QZhoh zuKs|Q1?hZ4l*u*07Q~vF{veo0u){?vRS|=Vode_90wgb1RG86LL5771TA5U}pyjD$ z&HiQFFLc#DxZ_}AIY_{&N*`X((svPujGabQagnrUluq$VL5n>wtfQo{w~#_X4Es38 z|18V^Ji-bPY)cLj4bG{Vn?&5Ow~6ji@_lS~6LU0&5Q#Bc>(Hfjc3$84;KCNS{2Y%F zNmw$s+)w|H(Daub83{*RS|bUId|5@)u|}KtNGnRm6w<*E#x}My1}@!rJc@P4TS+Nq z69%7_Lp|6vo&0B}u$J|Ti4gDT7|W(3-dYIfAO{9CXl;>^Ki|qUNpv46uuBdox&Dp& z%E(5mZPVok#!E~t4UX3MF#%x=u7D~MOp(idheuCNI?(F6fB5d~gib3*z48!*6Yn)% zaNxa-MiHqmy=lZ==Ey!LCzW!19{pZN8JgrGH*xtVxwR)ismX4=v8`mBgaxJdfc zx?JpO3fC0mSO?J`fT3sa*@iWD6%4Mcu`M)q7q7#D2!q zL@u&S3NId7rd45lAPFC}@0vxh5}-NjmfJ73QyXBxcHS85btS|uq!@Y=#7e4SfQ(mZ z3~?HTLfA879!;eML~fYPOscj{>$mEns0uHrunJ~4R=C2f9kFPZOp2H6>il8D)sI+n zm$60_@7Fq5P&6ql35GNBtTa zGlTd@L%F$cU0hum!ESuyI_1exgv>5$T}W)~>|-`{yKa0@9`$B^LqkJyOnQyKd!h)- zg)AH#m?R`52+U)cgWYSkUumi`*K);r*GwnmFfoozvi`9dJD4lW*vaNkJHMLaHigVU0A3-4@As${{ z`1q`>n3@{)?Ck8wyh%krKLJ)&R`5D~a+}4=4ZLIHDP6IW`=Q$Ic8+99Uq2Aa4e?0L zQNj6eqN>#00$cX+VObgC4-RXzL@tlDs2fS+8q0)NgRLpaH628?b6@3d58aW86~A!B zY6A5X!hkf566dG%7ex3ujnDYiS66s5G~VR18e-XyXkpDWQ@fYjf$NzF3ll{vZ<<52 z10l^CwH>X!8$e180z-mp7D@&(i67OAy)vFdrV7`H1WTGwYV)$R0hbQ%p*>G~i1uC+ zkB~uQkiI2*|8x-0kmx8}a43Y;AJtX0zTHEGo7tH0hRt0nwR*pK6sNLhX$KToc*Hc$0`u*dhUz)wfB--N^T&@>R-W&# zkC#drnq{=_>r}&c4I|6%7hjqfj$@}aYdG=@Vy>!13Q2UR3VW{VK^4riLbL9h6w5}7 zK1Nk)B?lZ$CfsWVj*J_^{`;88@+f(ne)QN6b$LPG!(LJ6UlFj`eR4^%MO6`hR0-^? zPqV+YpHE$~a8Tv?Ws>o9$3=Yw%qn?Yk*j&=5v+7%UuTDEM_t$PT%-l$&z*^1k?gxW z)!0;Bq+MqP%A)<=zD*Wd1GiY#A3G(gE%jcb6Vr%@G9xC>B$iRWgi9WG2`jN z%zW#rbGpM7DbOz;$YYip&_in;V^9g1F9G_lNI@5mt`w;?Im8{*w6vrG0)&o_kG;IT zb5u$g_G1Lo`Lbfi$5o=5OO63uT za5%W`*N|_=m!fBDkbxLFaanpt&};KE&KwEdT}d-t;Y{bk9rV(OsHmF8a-STUkuQcF zLYG6MKa?rD9PBK8%-$)U(GCm@6fP8%S+-PLGv0S($(=7i0X^=7PlyNKXU@bMt3^4o zkL2PqE4&!<&+htRhZlNBYGIn;T!U1#B$NBn9IX7o_#BL*F=Pl>p>ceJ@?t!NX6Se{ z;`=o2f*(upizIyR61+k0y#=Rjzh4n(Z40Y=$g9zoQm=!vwYq;gZsRm=I~yz*x9BNp zKFm~7Q&*wuzhKvDc-kkd);nSFVJeRyxW6(Uv1G>tZME2@PiRizqYRy&yF^Ato?c(~ zfr4f}2w#N8wM;(FQDUG0AlZ~aBHKgwqBnZk?G{E4jjf$+?eHyi!(9}g)C z+gTFR92rfQ#?OdQxY*ea*ETF^oo&~xg#D}#+)?!cRc?;Eyf;CYC44u7zbnxdnWMJq zYz52|oykhMY`---V!0kiiMDv-JNJM;b08d{!l}@32{ zEYO|`8H&U(G0f_m=fY;`m(;fI7#AY#`Eo@)S8vXx3_l8VRV+ulPLTpcWX9@TT5GZ(iI773^ z+t-&qL&d-#)}WG`vGErY4Gj$p5SYrAc62KZRogg-Va6=f z=$GB*)4G~4h7WG6uSe)|C6&py>|YI(bY=+*C3qZJ=P@+I_bT>DR+m>d*epaT+iB_b zQH|wY5aaMyhhjuVt`K3*XPUj|)l2O7QpImtlmhsc8UgY=*zOc~rconh8GB>c!vS4*4Ro z=(-?8FuW8Bc)!JsW?6Opq1;0`S&v54d;Mrog!*zML7ZGruYtS9qh`*6fUNY|O@j5I z>3~}+ojr6&({!M?u^nU%g>5S9nBp<5Ee^($k)*6Yblsf^DIr;Xt)3}02V{uX*#p&% z+iJpyzQg&rExZ}Z)TF|@^C>K0?KP3==zSAC5RbrzN||w;X>&v!y;3G>$ycerV(X*{ z7%RcA1jwC&B%#F6|9Ahy*tQs-dUP-P`FBNjl$A#R8&@Ko-SeU5c#FTqnG(NwlJlb*1&9A zgmm19*^;$6$o8;#%;tA2OX1{?x`lt3Z{zE73m8Jfo&?)S4@Juosrns z?3aM>0iQs$mVFk_I*}I^5)w#rb8|2=X*6FNF9R!%l$V!x43-2B4$8;5FR_)A1g002 zm(vkm(>ywSu3z|lZ?ml?YTl@~xXdA*ZD+4wpkI)=nO}W~Y>JxpFy|QO*j1l&&YSlZ zg^1u`*2)KjNjVCl*vx{7P$k?MCuK_?Vqe}TX97^oOlpWRWT|PO9I*#(M*%lrs>|F0d+V#+;X2>+ap>>j z>&QLJfZDj1A#JwWo@2S|KlL>`62bA>@AY1w1ej$#BM6K-GT`}~P}gJe!_5j9B_}7t zP_ST~@?Ho8vQ1i+!5$c$nMs!65IR{^d-!~M21a5OBjy{in`(4cziZ41Qw;LN+&aU) zSy(c&eg(#x_*`YI@-9!PCR4o$iUgYGur5*%U6?LhgVY*M&$OXj?D{QphR$#Z0of=G zG6O)B3fR6*uc8jG%XeM0!7c{}l(_d5u{Ch=g_@ zIY8P#B;LJ#vmYr?b$b>Jb%6!h_g4#LFMYo#U!Q+>LO0z#Fl3=|LUOEZU}IQ-Qz$bW zdCNEHJXEZ6tDkovf-TGzP1~H$^D<=3_orvgeY^(j9@NJVL!!yf? zFWM?9q6P*OOiWC-x3{xyTCIF^fR~h%lzMu4Fta)@KVN*V`#3*cm^1_lZ)Hy;b89$8EXO?$~LU=&35Hb6mP&>v196t^$q{)cRsC43u;QY)yc z&F=Wl%E7x6QgMN4G-A)Jan~JkCXbI=v6&MpGPLuqk`Y?3{i%|h(Qjfg-kCymuDO4I+WjN`GvU0Y)4%pJ+!@%hQ{e1d zaGLJa3tL&kH9I`Fvjgg$<+#vNVd!tUhOCGPJOu@X2DiSW6l`3WnVDgx!^e*wKb20+ zpS2EQT-!66@8XG}xgk#mxOuM|&pXDjmqnWiJL@i7oZ{)9sv?Yh#qc-zSfG0|cgsIe zXB7oPi{lx3LYTUFv~Y|u1>oxju)ecJwC)G@Ijgl6D%bW{D zf|mpCDdDmx?Xu_hG+yiWH5)n@1v<+O_iV;-u^)xvCu{uy#Yy+nvdaeDxhWr5Z6?Xq zqs92hktd3j`EY8!EqSGi++bG6-F${H$wAjiE$Zj`9@u-?ZAL%#LcD;EgsOWk zF%#x{(=$YT*1R-7A0~1IyZTlrEtEQJfAP>|GEvj8Ty*Z!fa|@TKHz=6ez&Lt*EUz2 zbyk*nU`J*2F-oHi6tbLm+ow55r0d(>djEI#gg}ZK8)q*u`C@vOmdIhdXk=8>k>6Py zLDblz3S)soHo#GB#H$&QTUX3ncZTEr=Iht+IpFL5+dzR&y$`0P3PTl{e$d;Q0=ZPd z`pynT%?MJ3TRaQOj~MqEfmSRnb3ToaVMb4#^>2fr8K&Rld7SUs#wxMd4Q=unmza8g zZ9OU-9~G8aiQ5P_M|;PZ)6cvjB^+!940_qinM?L?ZVNblIJundOFC24s@_8-1`w8W zoFG1Q7k~bT1ADz0IqB4)4i0N>#6)7G!lv58 zYWJm5#=SAq?tJ9!?d_O+E7d}Dbaeg0!#$my@Gw~-Bdg$(494s*GHCIohzoq7*m2IG zzo-)7?@7VW-vO$Y#Gph|>B#PmM(|H#_y4%o^Kf??6KA|mIJBof;V31T^%N$p>M?$C zHPgi11unvevs8SHUKzAtpDTOl=$jMvBUWuur&yT76NW&CT5R!;I#N~L`)Q&477W+x zR}iMa;66ar6zt^5{r^6B60l!AcI{1+V(ZT%ulo%@ZJJd%OuyEcWKk`F;u)UKXL0$( zRpgD6M-e@b37I?N3j*)L(q?WmTxB3Vzt%w~5rWw=9u!{4h`7@a@Y&u@ILh!d*G-F3 zb~pT*zEWk{!)IqdUlhWQ>aDG0e{^UlkM7u>+vd*B#_q0FjiYbXl0;}Uxoqmg786?} z)Jk~!IhD89uRS=KdWCr%dV-yJL?8w1cn&Us+O33Z`7p)C5mp$@c+*4k91;W`!2+K- zyTPDneFh&>v{M?6{6g}KqF%?QyOFMoP^e(@ zytR+!s~D2Zqkx@?V=_*w->q}A$GMTcZ)OzVR3c;~UeF#UAP)6f8ZO2DMQYZYX<$?b z43Xe|-DVJ|&h32lFLILco%dhrCm-c+7SY)x#QzENk^cSqZ$(`1|EcGHnW09(*T?N!H^2HHS(Y-aYbbIm#Xa(AQKIl(^!S^*!vm_eK zbF!5sd1xBJ;_^atTy;Aa|5y{106}5(CRKZ3FKd{gs)PH%Bp@% znkgV6j!h!3Rr`oUbA`!%$!2wXmv!lyT>hu$R23S62!&ynZsv3DU`rfqx2J>@3w1m; zdbS9EcVycIf!}W^%?rxOjPDXni65?+r1U$ZolS}Pk2%-R-}p|*g^fhKZ>cWuxDn`0 zhd$d_2WSoF{6YA0%U=CyT_fKWMk;c6vb<4O2%20fOVreiGq%vi74qhPCyo?Yw80FAH7wXYe)zfoj6niv+~| zGj)f{(86qQC?GX{KQUteOk>ye&#YkUrv9SzP=N;mc4KWm(2Aay{!K_h0ROj?r^Xad z14@}U^=K*6J0cpUHv-81#3O{jn7;K_u%o@V8|Bv}tVFW9Xzb%s-PW=}Q&NIQMBR>x zzspQBXP!dt+1ORP-OqcgJRN7;l?0F95|^@4d0J1ii$bqgx1rp;w{+z+2D7VR*b8fG z?dyYf%49ei^#K9X0p0FXsNA7n#FVh!%8bIFWq(~X|3#aUyDOJctbY*_;ER?5S5oRF zY>cCbz1Y|HEU!NOm-U=2@IfB(8l&v~6ID~8$(;(4-) ziZnbtTCikr;!HL)(bnvFlVq+Enfxsb_fq;t>>^0@f{})Tf?m|>lviv0>7nT2D#<$| zna006LZkPb!2gqOn&bF4jl+eWip%sD&PJ?%`EN30OdUlIE#>bVcP*+T{hJoui$o|4 zk^L*3#>4pj>Sq33=1NNOe(L#{=9ZT1flq$D(ZphL6oN@px!Iexz5A7ojj1=wzHv!O zui^as{89ydxdH+Lz=gTU-1D}~R8(If!p~%IgoK2Ja%rMwX8F}~?pvRmKHE;08DDG< z7e23ioCzo0CCRxZe}RgPy>qt%>>C~)&Rx37T^3BeLQCnoR>X`+HFsz-fpgIy(j9=6LbQG)y;uKutn}GOk%bW z^TFg_c5`g7R&=3I`h5}=4XRGFGRxv~XVWj@b=}r$So?mD3>$`+6Ig@IPFFkO@(T)R zOG6vC`P_CtNlSn8TWyklPeY@sqGB>OvA(_C8&4&cBp;d;5gly?PNE%GrXo?xf(_na zZ%S5{ytFi0LPCPLxcKP~Fpw?-)p;0tKFEA|y!6ogl+ReP2n>9Z78eiEdp?k}vic|` z8EW;({m<+ifnv$|QD4678Xk_pBIk3uzqG!)q$QDn)fYv;XfmEJy}7;ZvS8mpn-P%_ z@;Q&{-8*q@hLFY=DA*Kcu%~kA9N!9LQ|L-7>FfS<=Q;;AKNCfY6FFii@ruCQgfvJe z8NUaEW7`!0?4Sm=SpR_Y`gM1c>rPV7I^XL4zRX0SJfJ7{6)az-fOmEEeY1+`?<6N{ z;qmct9@p*Yk{PS{T5B@l0KKpQi9B>n%$}Kye@>+--Ccmz41T{5F?FKqtiIs!W`$-aFCBqx7%aHzNpS_b2O3h zFUK@z;jYeLl)>y&&E3!QVn;g4$HCszMqS*>Kk!lBn*776)O_{ z2ztkVYI{0C!M0A=4pXIxkB?tGWn=ye2UFp{*)N{B$(H+u=pS%A_B8qNU}cXt;K2|0D5LJgLQ_hmK$EV%Bps~Sae1lg&lWj-w8HE z7rMvx_4zqQ{OV*ZHYM z*N>0$q4&6l2WCDa1zQD~(h56?hFGo&rR)^v>HJq$f9HoJ=JR=I*3UhENmS>UT{^ni zY_Dhlnq?;>F8e5GkK`CsLS1xgc0u*jXeFrk!fwGm-ds0vz{Oq^;?e15dn7;qtK)XF zkKODwz3$3tWYp~A2CITK`QAKNYW7k3gs6J|NSox{mRD@`73Lvsizk`!g&}W9t<`6U zhln_r^E;Z3RE8Q|Wocr3rsGB2SD(UBJ;~^j`UcEzaxh*l`R&dz!RiV6*2I`JrZ49F z6C<-ub*#kl9kw{>@k&h=b90y7^&x-fiB640kIuB6@JM0a9S1h%56c!KKE&pPgtUR) z+t*C5ISpVsYtk?aVSBtlR=e4)1g6i7sgXk8KRTZ>YkaU!#(HfXHS5n2ir&=o8bGgW zm~5!j9XjbYO*V|Qsv<3vH$tD^Rc)D3;NP2^4a0~a22hXJ)PWWyKCZKkD?)qD8z)`^Qk0a2i#;{Yk;cbVbu7Hhn^8j9*0?P9aal8v zYkwH#)99Ge_(>Dbi%L+t;`_X$r!3l3;cd=168nzB9if9@0aMIcFx@vcHU_4HnHjR? z_f5~PxsJWe zqo%!i7}1goz*+BAJy;0-b708)08nN=dMB;zP?4K7ffkVP_-bA~iZEr782|jIW700a+6I z#ZD^xtLukDrrjo|X;@8Vy3 zMu4_2jQjD(kyn?noK)AwOAxx`VK3#yFwdbVWCYux)QgrK)N61=Gb}k zO2|uNVF8JU4~OXW?=LXE*7CIcD`KPCja>y2XHL%W-V$%wxg}~*V9_TB+wHK#>XPpn zcnzNsT{Rm}VHFH~DgNL^yFkRtJ5ewHF)L`v32rjBqShYIs=317(N^I{xHH-{z;=8Q z*wQS?lJ9FvvFk~XjcEtD9U0~UCTI>W4$ANeO5pR+$wbX%rplBk#QA<=@0Gm!sQY3x z$Nycq8nGX-=c}krXG=*N3N1p>Mb!P)F&|OU7vH{plgk#+)>fyVv(lfX_nos^TFjz8 zu^5<5<~g`ZN}lq^FP|TKWmy;5)#@sjS(DJ#i&@54Y(=mNIm*&?QIzA+7ZY?=EmbZ7 zj}j1`?L57ne*f4LCwX41*N;wz|CNf7h+rZN#kXEOr8#bov^t`>0I977k^M&y+208{5#bN9fy5#$Y0xsi0%~7if0tUlL7u2_a^u!`tFQF_53t{@;W1sK-2Ox1K7> z_bAumio##Iplfy53RBt%i1@&~4}+AY5Ide+-+awZx!o+MObdLcJD2-8J6q^-fARa8 zXKkTvDoOy8!jExf6&>;YGdGRrd%_iHK!PlIr@$j$eel!01j@v7GAduV&-(t)b(Pq# z%8o@4KZ*+8`0V{1>nwbZ$}JjmH@&yM*;Lt7gW@9{6eTw8z*sg zCOcc($(e#)XH7YB`|EvQ$$h;qql8E2JL_Lok2U*$kC{G7x!+1L43O8h8ipBoQi_U2 zzBk9^Y|`&m&Q%YHGX;=cx3m_8C$llkpVR-=(qi|yjB zLCDDwq=dcG0lrUfkFhbCo}OwQr!q&Vm=2d+!!EYrj z2v&~#?kqUX-gm@kk-fuOiHKQnG&KCaAxG>BX?wfD;`mRriaTw)Ip6eIXo;Ga&lpuL z?NL`7Z{V9yF>m*M+t#76Q24gDdy_+%?q}`6^`{I1$e|CBy61e@Yg`)uA%A;NzyEjlw8-$VZAU@guntiUe_#ri6s=z3B*q#k$;5p!<%o>cmLFahtmD z%!g`OeL$bfU1y256wwHJRgXQ~Z-LosJNbOe3R*|i9Ll_2tQWw%J6#&#>iValJYaW? z&x&+_0^jhB@X>a*H$RU~VOOR08wkdUG>tF_`f|MH)=QVIuZC_E!NGbYK#&D&Ht2@wCV%t9!ILl1#P~WBrsP)FZPD@i-9iTFS8%kSCyn8; z!uC!+d)Z1_|Hg^EIpjTgwopKH$1_Fm=Tu07eXnj}%Q$~`;&`o?-zCWKG1Dy?yJH^W zEy%-h*0W+~Cn%c;&RBTfbo-j)J2KIfv_<*YbqGMw2D*g}qtT?DjR|299ync{TZ(JO z4SKe};3Z_6Gx2F7+o+*@HhU=1@nIU?9n0fBg63~*#y!lYm7**Xar{Iu?p4h>H$NA9 z^|}DKV^vtUx-YHtrCJWvIj_VOrX2MkYPBZ|3E?k3l}fMm$P*@EzB%HE(u7JFBi$l< zP0%+=n@gYtLIdJMSDvLEkTxwWf31Bv^VP?wO(&}_+(O{P#VT^0%q8gO>mvY3(Hal? zGpF$LTzrz_`9ZU{%lk5lDK0eGYQ#0iMe4S~pkYJ8p=9p#3mk0BlNkE(PmwIf!{m0lpi8^Nu& zfdq8TSr-%9B#w=)@qt@}-U~9?v}Y&^)tpl@nhilIrPS|Jz_fI%CnCeu( z-Rwk}q#YYkYTd+e+t|X7((so>>o6P)Gbk~2?m=PxD zxwsV80q0aO+Ol)M%O6Lx3puSGm1XIG;aM-NANws4d6;x4&;^+$U+0OyqwkGg;~o+15Y;X?R|2t zjvx}3f~9YP3Cdbu6T@jdCGYZFl-PNi@t27Q{G8uFs+~2ckdoiSEGHPrI!GYO!B?05 zfgu#8$7iudwp-KM!MuidE2;rE*fu|Hxx}y1$WEUO>W*>A{wmn&?#^0Na)LU3mI4Vg8`N*CBw z3)uWR+$4~AC8h$y>&n%3-ICOI;qV<|Z8)^G?Uvmm0-2&rdyDvQogP?mV{LgnavBvx zc4a~uu&BFc*x;M__}8}_`~xN7!ojE7T6&Sz##}ahi{nAo*q56CW97wZy`C}Z62BVu z(8Dlc0N1M2j)%yt`bB4MZCMa*&rQ0f9@tV$^h3`VNh2OtieovYzP$cr;4XEJK{2MFgpzzXz6$ZzgiNMQ9b2Whq^b!kq<;Bh)g%o zs1cg|!uVy6T84FI@)S`zTK2eVML z4Tsl?g%h=zQKr@JmT)W-?oQkZpHCYfEW9oe^h@Kmeb)yAlL^CXyDv|MCF3O4RF#Lu znYk{Gv!e>_L!m?jX*8G0l?mNYqC7MoDUrm3m0j&(lOZ8te}7KQ9kCk_;|yJKV&WX=9TswzVZd!K!<6K>$bW zg7Bi3Z3cbyF$-P}Q)n_taT9OTL%f$xQH1<#iBBk$CrRh_xFmcDV%1KoEw|%(Qu4JVCjzQj1ad=fA~3+={-HX0uCTvAGVwKQYj;BVyqBh)exUh~U#?`Gv9OcaIF6Y~V} zV7joXk_mde;jUTNf|md+0kE*J8hLrw*HPzl$8A6f-|0Al1fR*IexTSrA6pjo7AkAy za1Xnx@fSOJoUM)+3wpady{Q~|pd?jwzpX{xm?%Mrz;fI6+m|-bsS5X>mwl~SC`Y4d z>2tFSemo<08WQO2ZtzS<(uLyyvXMJGz}*&yY2i!g3{H zkVZL}eBtx*r3}mF?mR*vp9RhUr2cCjT5Wp6N_90?#d7P}qY_2z`I^_Gp zt@9!=EkJJ5-Yav_3)~NF7wnQQj0+ghhv3J9Y0+#SU+NA^Z8iAVXfMBaCs-I?s&Tj5 zq2$lJI(l0m^lW9jhhprt-{VNYs$B>jBgP?z5m+eoTKc*Z=4#L<8iEreR?yW@f->?2 zEE1ZLD7F+JtxlIoPTyy*j@8J+Ys72uL$c=iO=93kexsg*mzrhrP-C!fy6@`2T99Kr za~_av1l==CrGgiX4%7*gg_D#-QTq~AL)dNrMvJ7I1SArWPhs(>muQUfjaI$nd)G*N ztPp0JQ))EWD?F>CCDRne%wDuI{9JeQz8{2SNXZR@8atnt7E(^K_vD#R(%X^yRoE$K zz?CCz`H)?HuO>^?E(ARc;nHyQhEVRUw2qsdtF>}xCdhmCzW6s6BiXQ!fsr4KQ+PPj zVc3KiTW4HC99K@A4J9-P$0wli4$t3tZ$i;3k2Y^$g#VbT-vEo>;lhUqU+SgPE2kVW zEmUTq#Vi~eavPdJgA6E+?n-kMyaoCmeUab#50Bpi;GWo*6?%fls}U_{Br^%%o^KWo z3ST1okB`#k`A6Nbq8ljeskM2IC@ik56s(PfLL(234-Z8S;5ge2jzc&va`sg}?u?Ek zX3lgLT5 z9724BSO;+=-&KR0!rHP3bUg373C`&XlKK{O8%hva5BQ9TYWy*$sJ$e_;PPLC;?$%jC~TlP9`)s82zYu84U9D zST8XSTR?y=j8PAfYNFuxNbG3+VnQ5mo5Yr9RY<*lhD|nq1jOTq9nzT!{J6g}F7-u7yUxdJ6ui(i1aY{4Z zqdoqoY~c_u?i5wXlX5xnJR_o^B|aSr4WCDAD9uTeA4N9F^tUnpF6*O%=scO8rpbxN zsvQAs~53M6wwUywObnjQoJXjdtjvcrqr5xNIn343c zl}koiFuvF&*bgq9gTfs5@%aQxiY9pCjhl+%gM+CVMg35*uXDcDP{;l*7ybG#j94C=5VAzqmY$xT=SY%LJ_=w)*}8?kH#6Ic_o~3r z53O*B^2-z?n&re{u0ya12P4T&sch_QMbfcn0nm0>fyzHzoPMNraNBqJS+8$LqbnKY zP}8u73oC5LYv$D8dZ;6YA&!=WGG{9&Wdizg5(%Z5r`9ORKAoT%juaZMD#=iU=|@kx z?T>#)^#r*hwXGeHMafF>Br9l?Adov^Qs;h4EJ;z-%*lKFo=h%HOaN)1lXN(EEh_6t zLpE$cIOY0wbS4d*W~A!LN@2^!(XzQOht zG%EP6u2d`^BPd=~yfz%q$PNz<#v6&{i)7%dguMq6A~f6$@~g==W%oVWekO4h&(0 z5i_uW4U4&I^JrrBusGqT)O8bYSr`EU;|!;#NLa!#h=VdR)@-}dIjn<9OXp_#{yGhy z<|x_z=1770$(5Ft(mMSU+nS@c^Cc}SYq&RtwCQ4mAE5rX7SYs6TB8r|-m$>Q#zOgw z&wofmoxd~-Y9g!w|G-rYdW|@+hz;|)zkDhVfel7#PfyRg4DpwFi>P z3zB7SGn+?u-JdLZM?*uO@z2ZQ&*g>IEofF?oJTSG-3Q8tcPpEw9X5xZ|2SCWw*RMR z#{V3FJC(+6N#d6fr&Ip9T!TI;v)yb~ zWoLaQ{$eytG^6zu;|M!85n3KRGr97_rwmJFoG)=t!@)LzjFwd`H;yR-{@I{ReF$L+4ZTxzf=xcJSA z^s}p@`7r19eivi8Xyf}uZEe>nGJU;W{E6?K%JR-gZuhv6GD$G!jP-liTG6Yqh}rY) z-x>dkZ}|kUrmum6kQvSG(S=gdq|@T|UF!DRX|V)qbx@a12KLR778puQn$GTj$s? z$UZ(E=MObmZ9aHmvc>caNj3E6%>z!1bWDWT$j*!^71L zK|)$jw?g}O z=*Y{<8?)jdxPsN67(D-#-vPa6P^9MsMIk{&$)l-SuP@Y<@OJkB(Zfmx4gHd};{bnR z`?U#nUhfuPR&~Dx9TPycf&m7xAIO!%Pw1JLy!`|Do4_L0`a3%TKRz%O(}4;(&F6M* z{Xou4$-0%54ah5XnlLG1oV>39!ep*YyXKFm!-^3Iro&p1Vqh3n-_2sQRBkGp{IWue6 z*0>2_pl|CQK$rNBqCW#MZCGGp35)p}7#Y#fK%;Wt;v?5>pjaCXbveB>U&lkxKDEL| zUNp(LONMO$6^5M1Lx+cUFyi0%{u#!H!)Bug=3ASa1q<+WW7^_)zEL0}orqL!@*Uf` zUeIFkMt#m6PtPBv=xJTLT4EWBE1b?FchS^eDt+aGrP z%l!S{4bn)Av3;8BSCMLQ+EyeRf#o(mil&llno^zHWWx{fbR5hLjQ#0n;7>$45v|j( zfq}Z7l@^@lk#Uvmk9@f*teT6at}&Uw*PmiZLDY?1x!5<)3rbrl3ZuTeWwi!7W$#bF z#vlD@`WoFL&g|%rN?=q)2m_UhBM_V@xKY}pfuZ@1W(P+iTI?Y&K$nVFe1Yy)$j z4oT4ze42-GfL3)n$mYKGU((VcQUQ`s-)pGEJ{f zaYToopcZ~>V7IBGULN+hUSUgZC-=LhKO@^=(yqAlxV|*&hI*ckXW5_T1)2QNP8DX& z>OvD8JXZBiT>;GvMm-!K4qs9k-zLK#41=#3MTBiFi(L^4UvGVQoN2i;o}oTrk18Mt zArV2>%JE+J!Hs9Gq^#q}hpaaWrdl@@D!gNYe33J~SKB%KqD@mpAtwQRF)jlA!f#T2 z9}qXRG6!xlRQuUVU7g(WeODBQ0&8g+yo*2nEdE{ajc}>CHs3K7p@VYxUBl3+-l9O; z-bx9kDrKaFTaxfGUBv!)_HzsW_llhMko%Tg-sG<9+Rw|nmwab|dFEeB|Aj(h1XCRx z9AN$keYM!znY^wrP^Mf~1l8G<)lT|y>!v03;_Afj;eb~rQ_qTYF6i6F!x_YP0e8#( z=;5s(k-s5x_U=OFy%KCEsQM+GUQen)$aA7xTehn$QtR3EEwf)U zz%se}3{n@)t6y9wFJ&7h@t_+3$e<f;OM`W|fZ><)3cT=z84;8{W<^TPmU4vN}i+ zB8R6hfd3|TZqXGxp4plGe#KFKuXaAGdXg8)fw`Ga(njkdv^lv? zCZ_p%&nTdvSnAZ-iAGg@KzwLiwepu&i%DO?9gwBw8&^*m>{~fBI)4ymzgP&)UlomW zAoqS(m{wBWQp5~3)fwvm2+LG zCAHBA;ZH_SV8Pa=btESc4H6NyTV+Hu%5c&JiIacuZQpr;xNfaC^ z2>fn+egbE#9GYG!ALzysnirmR?jw{5e-{%`rbUuKdUq@^#5~|#JgMMjw}io6(|2)t zX6e_V;l&52;yT90+9XhoH|$Ox?wd6%?&5tDpMs3Mwq_>fFQ3t{S^~e;xXXTb+-DZM z3FA}MWcJhCgr3(lHI6&H?p7_ndp!3p2xtAs7scKk%Wz-RP) z@Y4rw)m2`f-p_QLSK_1D2~4q&_QHJg{y1>T<8SX&-50H-UCc2B@TAIri=r1q@z_bb zwrESmqQK~2kN!l*(<&UJx{dOwuPM<|``LOI0KB?sHAH>Lc?%YCp77 zZ2xJ%zNS^S#eqjvQ7uj}@|yud)1+OAY*+7iFfi~r5scp5p$5nJeEr3* zx`tmm)5@dcXLIsAzQq`niPqhg9ti{ARfZt*;o@&i1fnJgN=UV$3%zIOO4?so>Rk`1 zy_obQ>H0{?vE`b!Psy>QOINx{siY$4nJ}X#CHDEI@tBXK8}6e=a*5XEo60{)^<72V zB}~DxB_>|{KdZycd5QWma~n_R@xru!o9YVUQ~WGRR+=7|UzrIg7#%1sJmfOjy#BMb z+L=O3=IhSN$QGx^q9r4-{bI)`CwY9&jzzNbc6LH>TcI{0>DLO3O4{G|3c%Ov*@c}f z!$#nTD%P65*Ie6N^2rIOdpD~u`D1eCnv?UP-V(W0keGPv;`$M`P2NW0yhUtF_ilHu zTl-KbS5rlEb8+sjGyiH@Lk&(tSW6VMXE1SR>ex-3V%cJ5s=U1Tpr*JMU}jyj`Hi~- zj)665g=nF;aQ?(FN5>AW0?xbkGh>yk$mt~GzCD@Zpq%aA^*)b>Na&r{e~X-ayP&UF zep)hitZ6#hX!EmnZH%`6gT|>&b+Vhc@(o|)x;fgy!Nu}W8pIc@nNti7V3x$&1 z*o!WI`XjLmW6f0H^L8-!_R&55KupTDUJT8zm5Wk0w}1GY9kx7(auQdbU#?OFJGs&u zlXiHxOGzFtNP?{$*v+$bXEqpb9OFblE$Ii71Wdn(cY8UbmC?!V-I3yf$5O zhw73gZzB=+n#w+(*F6J@4{!v{We zH-2k-#3VxouuPaUbAg|L=I!O>710bjjs>xhq5BCpMqqML=J z^fW>)2KZB=2S=k7IfR}Wn1||r395!*(;)^r+B|K6-Td2~$m8u%>FmF*EO5GK-r{n< zT(pE^L^0TdJ+hk0i))L5HQ3Uvsc;;$pVmVj>cMav6j_gpH&{KPjPTBgr6=&4>Y6(n z3rn>9euuQ&MrhhiGLu(N%z7u%LgC_4U{#h%6))eCai2lR6C(F@Cc@FTh{uvCtH+kx z)E+&<^SJX^Om|3r2D5N{H%64k`f@~fQK zjysdUC`R)5J+`Tz^UsS{t1 zjgVHotxGL=Z8g1P$zg_C`@>{y;WVSn2fY?ASM9WkyLOgb~9gG}5 zq>(Nc_lk-3v-A*wGO()5Qu>{qiY1yPecFO)fA#LIN}3a{=G*%c6Y;bX72*WaalPyN zPZGttPu_~Lx7n}Y(LfwORF&vkr$UsvtPeM2`$*cdGJ9YyS;2N+7faB@PdGDg>b|Ts zr5y|2Vvw##F~8?HP5owCojXqCN7rtREjK3OyL#$U=plZEc$Vqfw2$RxQ$?-rZ7yj0 z$Qhj5qA_M>VMWGos4lb1xCm>=BD;uZWT>+@zePS(QC-o?&KDsW-?TE$DB99uRGaT;VkzpR(>$Jn^Ev(H#urH)8+_K@A7J*Bz#2^s)e^X4_QB-$etG- zIMxM}=Bnh#Snb=Zk&YVS$a z@DnuEJgrytDr*d&eo^;1c%ON`!k5&Dd%r%1^=NV}psps)%a%w>0Gos=WX5&^_DpS7)Frzd~%K zA}Y4qHxW1EJtB3?%S(VBVxqjT4<^ik6if1k1kbfg=_|F!^0nRH*|U{~>%0jSN}LB6 z)Nym1Ugs45c{*ECDVhMMT^>mlu-yA&wV^p^_pz9bv5&A(xaW1h`^PA@#Z zJ4PZn+llhOwfFEqm4%kMG_-(}AD}P8uPdA}+g+hEmjFRyO?pXhj5XTZw0=#3h+kYh zR`b`#Z((6SbHQ2|&`@bi?ZUTf4P{tZ{5u@@Zy&`!W{^$qqp>ll9!j*0c>WVHF*-OL{@?xwwHaAdi)bX&W&a&0x~|>_lMTV=7Zr`3taij6&!ahV{>6Lx z6oR#3C+$4-*5}7Ipykp6`amL1I}ZV3R}=uXVM0{@p61$GHRKAh7Z4hne`He-E~5|I<$qj&vdX51WO_?D2n*^QyJfCpv5Z zcDjK9*v?Bw_bXKE%)p`<`+bgx=El&>_CY|hzgB3``?AeUpUChV`U0#&voxa%@!kLV z`3fJ)twF(A02Qanz4@bF*Fou8`o;Ur$?Eb3f^^XN1q7;pOHk0QAb6jaks<8#&-Dcg z-@>2f_QE|Y!pQ`d$hNUNSdRSN*_kyo zZ552iY%?}Qt6y!q%C%)?yd(#a7?E{C<{YcxxAIi zIF9oeEsOeA<{xmu8nc#HJJtE%7k5EXJiUXKgw&#aL0($kLr!xJU2e_L2 zPb3(rcG48&Ocp%h5iIe~Z~zj!N}s58y^64#Zff3vdc)B8OVWgf+@fD@>gMZDO4AC- zlHV*Zs(F`_Lg^DT(NvQ|eR7V;yHz-2nnsAp#Qa2!spJ10G257LkLZN(T$6A0c zL^ihNdqjkfpP%1qrEZR$8<)iC3LuuIj&xR1+ea2Me+g4(QizuN`naBfY0)XLI3P16 z+3QiCat6g6s-)cFwO4a@@O+_Sw>%vt$94xel%u`sc+aJ9UDyiOs`;(eF6_31@?4n= zxGZLs@W0t_*YU|&FBa6G}+aV>eDXS&WyxqZI*LH(tMfo%Hi3 zUM&KRC|GWSNEse(jJ8!H?dXL*{j{2{+nA{A-=FX$XK1U(U050QuYZq>q)|oCxTf7V z6L|2ZW5AG4!cF8Yu5v(Ne|S7aSUx;-FOd+J<>2&QG{UL$<=3_(`Nf{>z1@xnSd%`O z?^m*UKeR`oh@2wyt?byN!{1x8p-GOnp%3Yh9>}|8Pomc7=V~-!hx8C1&yV^%xCJMt zo$`WfBWbf}6&{Gzww;)MqUq;J9$vpmO#V(?_gl~^4J=EQx|P(5Ug=fNZSHhr$*I%j zi_6dJ(;@xxO0jLh!O+~iWG&4I2pvDMVxVs>R#R|@#xzL8eu47E>R*RC+v|A=`36?MeCqoNaPC06jhlSQ(x-&63FTz;LOVb& ziu4+;sdUFVqZbU&(2u*g)YK=9jg2Fv<}_FD2GVpp7=(j{Yrl25GmoKtt=qH*4hm>+ zPA)Fjb_U_dJ9q9hfZnsB5gySThDWrsdrh3SDwj1XZJ8&l?D;YE$8$k7;3r+EW&UZmzG6qBt3A44&}?jBm)9b*h|zwQa_Dz;xZ++8eQ4Tm7aB$>?Gkt)6n2e17y zTg~Pmj|N_7;oFLQRJm=!s?+Q7a0R9{aR1a2)t&_u^+Ff7RF;%y`-LS1$&gD%i@W`8 ziN`1B-RY-aySZ{5ln__if9~MJ=f(M`cH)2cnABGS9XUkxg;EtB*7CZoErTkym01GTYEsl!{mS z!IHCddTSk@@*$6S_db@Ci4K{Ek4^GpyT{>36rm@gfE5aj-yARhrQdYp*JIVit*x%Z&GBd{4@sbGPhDygXpnB- zfL3YjOIuFYO+I?|o;K?J`}h8Vd^MuxrCJ{h3~0qZn_$Y`AW;WYFc^#)T@L!6;3>W9 z2Q_e6zklJF zc1%KoQaFpEe`u(>`in)Z$4Zi4l!UWwZI}N0_jj+DFACjIX6Cdu-*T`aYqrUcf|1d3 zO>}d*UJ3%;4`Y)VazNn&`uIJu&rgeriqg+$T{%Le;Hs*WY;0_5jixWpP_5hh2W#4C z##X0)R)JO~{b9pqM70Iugof~g<0Xa!21I~DU2D3g*c7>i*aA1`t=XM;(v#{DCiP1) zt{J$#Y_iXS0cVn-`e<@~GDSLcWC=6?gtpD9QUjGWmN9#C<0@rz19Zo9&A@@u$*H9& zeJTy8&ClWWoQtLhN2vSWEw}g>ezndp-apxVg_#{ZO^D1uIJbRPn7^G}I-|u9H1Aqv z*V-el05v(>*#FkQ0Mv1{OIdMNBRn}v$dHZz3r^v$F3bPKiTLVF20TNX1YpsbY6jS6 zxRqbMb?s;7%2?fBA=5q|$0=tbWo2bhOs)VS$%pD(rc4wdr4mqwnwjSE&hHmhP*Tdb(HL{u084UW+tQWd+p<(L6qYN>*3AW+cJzYI*t&JCt)GF_SCo{L zPq#)3s}9%OfJLPvp!1u+h+@Vx)^8RIMVRC*x6m0V_W&v7kd+?5CVPy4HBBkja9vBb z84=T>>U`Xb4vWMXXJf&2lnS@UfSUrge^20JSQclEg$Qgi#s5sQE7=0o9aM}$`Mtvo zuet1w1fh$nt;^YTs$HwFJHdY7y1NG2KUpsO#!rkdA*K))Wo%*jPR6nrw(B5!L>`bt z9X8%u$X3xtDFWJ6LmP$zWP@^P?+3?%&w#?PEJl< z87@d{PG*|#aY5bl3(HwIy+ux*u9BgYo@6=SDdJed0>V&AVPV+s-!fB9^C9eCBt%4_ zSQKM4B0%B`mcCfP)Zqp#!AwFzKR^Pa$yr?NICS|AK0K~YgWrIEe0rvJ@zRZX0y>#@ zIV+TCaFt4BZoxJBJ6MfIw{wvNz2Nc82GMl;TC(N_@4;=(=uU&Oo9Wg& zl#DX{OG5;yMN^ag@#?U=Yz6qMk?)=v1;(YraAKQHFuk32S?B6!jJkRArb4Wc;%I8` z=15VKfH4mnTflZbE`ise<++j72yo?Km#A3LI8MoHgG^^Mq@V1|ZI8XA00bmiI@ z-+BV`vjbd8U&sT?1C7Cez`zfyeQD}6t=EZ&u;W(sMHb^iMryV9{Aw`zqZMdlV3J^Q zjo@MEP0;}5{c{&v~~TUqp%A?pn_40 z2mSh5Q^ms;w=ZNE{P{P2!bBmoztanZqSaBxW_+5*6Vg=&+aK5N2txk0T#yv_@TLaG ziYaLt(XmWZRQt^}o^~DybwvtD@mwWzAoq@;&X4)|p7Zc~aRaaQnYB28?Rzmh3$KlenMs zz2%9fKB)nG--^mgwpf8G_lwga$8CfvI~5otUIoG{#r8B#MEwAsz{}fvcW>{*M1_rv zoLtP-*-8r97TiHiO^w2rb`gd93=EyIR&|<2vw=m+y%KtKe$5~$=JG9>cA6&xp3=<5 z!;Yu!_z`fVW%m+<@{85UU(j2%AsVZkcAIIO7cp>!mpFDz;K+!^m6r#e-ye-O2G>fB zHn8|JKH*D7uVCTr?d=R=E2nyviZddjRq6HXtm3h{{9rqQ$;ru_Tj&R(w!c3Z)kAkd z>Qdb_o%Fgl%GW!*jCI%OJW}m)XL!(nN3unwK%yDA*Qn5}*S&>K^K)jno{y;?pFMGU zg&}+mM3%bkU*`r)!mg#0m+N?Cs6N&-Z6AD4uKaRR;m9L>shYY=uSMl0+X*zb7(Zlu9s;x=2 z{oV(usEYO+k4CgWY`%D~2x%jOXC4yu%1qaWFPOyh-w;ea`!tL(BA=5wxq;B!i+-{6sHs)z_8_$FgRrNs;l$}mv~VI!eY93j(c1fB^KMyE zuL&T!XK4Y}t3A-5^uejQu`J8CnZUfR;2P|;U^LwhobmlJ*OkB}14P#20Qu}q7@#gy zJkdjd>gge)%L-Evm$yt)4)-g|(c-W81UFP^lWC-N)K%Zf=xNMQDYsYLrRmm91!>6D zfShcr>cJzLIkP{vD@`~<1ZB9_lmJ>L5ujxXa74>}aOvfKVIQzD9`CiRl1#p|p4a~X DeWl?m literal 0 HcmV?d00001 From 3795b2e39e2095f0de29bd791d6ea4cae205f13d Mon Sep 17 00:00:00 2001 From: Adithyan29 Date: Thu, 24 Jul 2025 12:49:56 +0530 Subject: [PATCH 2/3] 971536: Updated the content for clipboard --- blazor/spreadsheet/clipboard.md | 52 ++++++++++++++++++++++++++------- 1 file changed, 41 insertions(+), 11 deletions(-) diff --git a/blazor/spreadsheet/clipboard.md b/blazor/spreadsheet/clipboard.md index da486e607e..b2f13d9947 100644 --- a/blazor/spreadsheet/clipboard.md +++ b/blazor/spreadsheet/clipboard.md @@ -44,7 +44,7 @@ The [CutCellAsync](https://help.syncfusion.com/cr/blazor/Syncfusion.Blazor.Sprea **Cut active range** -When this method is called without any parameters, it automatically cuts the content from the last selected range if an active selection exists. If no range is currently selected, it cuts the active cell. +When [CutCellAsync](https://help.syncfusion.com/cr/blazor/Syncfusion.Blazor.Spreadsheet.SfSpreadsheet.html#Syncfusion_Blazor_Spreadsheet_SfSpreadsheet_CutCellAsync_System_String_) method is called without any parameters, it automatically cuts the content from the last selected range if an active selection exists. If no range is currently selected, it cuts the active cell. {% tabs %} {% highlight razor %} @@ -79,7 +79,9 @@ When this method is called without any parameters, it automatically cuts the con **Cut specific range in active sheet** -To cut content from specific cells in the current active sheet, provide cell address as a parameter to the `CutCellAsync` method. When you specify a cell or range, the Spreadsheet component will cut that content and place it on the clipboard, ready for pasting elsewhere. +To cut content from specific cells in the active sheet, provide cell address as a parameter to the `CutCellAsync` method. When you specify a cell or range, the Spreadsheet component will cut that content and place it on the clipboard, ready for pasting elsewhere. + +The available parameters in the `CutCellAsync` method are: | Parameter | Type | Description | |-------------|-------------------|-------------| @@ -125,7 +127,9 @@ To cut content from specific cells in the current active sheet, provide cell add **Cut specific range in different sheet** -To cut content from a specific sheet, include the source sheet name along with the cell reference in the parameter to the `CutCellAsync()` method. When specifying a sheet name, use an exclamation mark (`!`) to separate it from the cell reference, and the Spreadsheet component will cut that content and place it on the clipboard, ready for pasting elsewhere. +To cut content from a specific sheet, include the source sheet name along with the cell reference in the parameter to the `CutCellAsync` method. When specifying a sheet name, use an exclamation mark (`!`) to separate it from the cell reference, and the Spreadsheet component will cut that content and place it on the clipboard, ready for pasting elsewhere. + +The available parameters in the `CutCellAsync` method are: | Parameter | Type | Description | |-------------|-------------------|-------------| @@ -200,7 +204,7 @@ The [CopyCellAsync](https://help.syncfusion.com/cr/blazor/Syncfusion.Blazor.Spre **Copy active range** -When this method is called without any parameters, the method automatically copies the content from the last selected range if an active selection exists. If no range is selected, it copies the active cell. +When [CopyCellAsync](https://help.syncfusion.com/cr/blazor/Syncfusion.Blazor.Spreadsheet.SfSpreadsheet.html#Syncfusion_Blazor_Spreadsheet_SfSpreadsheet_CopyCellAsync_System_String_) method is called without any parameters, the method automatically copies the content from the last selected range if an active selection exists. If no range is selected, it copies the active cell. {% tabs %} {% highlight razor %} @@ -235,7 +239,9 @@ When this method is called without any parameters, the method automatically copi **Copy specific range in active sheet** -To copy content from specific cells in the current active sheet, provide cell address as a parameter to the `CopyCellAsync` method. When you specify a cell or range, the Spreadsheet component will copy that content and place it on the clipboard, ready for pasting elsewhere. +To copy content from specific cells in the active sheet, provide cell address as a parameter to the `CopyCellAsync` method. When you specify a cell or range, the Spreadsheet component will copy that content and place it on the clipboard, ready for pasting elsewhere. + +The available parameters in the `CopyCellAsync` method are: | Parameter | Type | Description | |-------------|-------------------|-------------| @@ -283,6 +289,8 @@ To copy content from specific cells in the current active sheet, provide cell ad To copy content from a specific sheet, include the source sheet name along with the cell reference in the parameter to the `CopyCellAsync` method. When specifying a sheet name, use an exclamation mark (`!`) to separate it from the cell reference, and the Spreadsheet component will copy that content and place it on the clipboard, ready for pasting elsewhere. +The available parameters in the `CopyCellAsync` method are: + | Parameter | Type | Description | |-------------|-------------------|-------------| | cellAddress | string (optional) | Specifies which cell(s) to copy. Accepts either a single cell from a specific sheet (e.g., `"Sheet1!A1"`) or a cell range (e.g., `"Sheet2!A1:C5"`). If not provided, the currently selected cell or range will be copied. | @@ -357,7 +365,7 @@ The [PasteCellAsync](https://help.syncfusion.com/cr/blazor/Syncfusion.Blazor.Spr **Paste to active range** -When this method is called without any parameters, it automatically pastes the content to the last selected range if an active selection exists. If no range is selected, it pastes to the active cell. +When [PasteCellAsync](https://help.syncfusion.com/cr/blazor/Syncfusion.Blazor.Spreadsheet.SfSpreadsheet.html#Syncfusion_Blazor_Spreadsheet_SfSpreadsheet_PasteCellAsync_System_String_) method is called without any parameters, it automatically pastes the content to the last selected range if an active selection exists. If no range is selected, it pastes to the active cell. {% tabs %} {% highlight razor %} @@ -394,6 +402,8 @@ When this method is called without any parameters, it automatically pastes the c To paste content into specific range in the current active sheet, provide the target cell address as a parameter to the `PasteCellAsync` method. You can specify either a single cell or a range of cells as the destination. When the source range (copied content) is larger than the specified target range, all data from the source will still be pasted, automatically extending beyond the specified target boundaries to accommodate all content. +The available parameters in the `PasteCellAsync` method are: + | Parameter | Type | Description | |-------------|-------------------|-------------| | cellAddress | string (optional) | Specifies the target cell(s) for pasting clipboard content. Accepts either a single cell (e.g., `"A1"`) or a cell range (e.g., `"A1:B5"`) from the active sheet. If not provided, the currently selected cell or range will be used as the paste destination. | @@ -451,6 +461,8 @@ To paste content into specific range in the current active sheet, provide the ta To paste content into a specific sheet, include the target sheet name along with the cell reference as a parameter to the `PasteCellAsync` method. When specifying a sheet name, use an exclamation mark (!) to separate it from the cell reference. When the source range (copied content) is larger than the specified target range, all data will still be pasted completely, extending beyond the specified target boundaries to accommodate all content. +The available parameters in the `PasteCellAsync` method are: + | Parameter | Type | Description | |-------------|-------------------|-------------| | cellAddress | string (optional) | Specifies the target cell(s) for pasting clipboard content. Accepts either a single cell from a specific sheet (e.g., `"Sheet1!A1"`) or a cell range (e.g., `"Sheet2!A1:C5"`). If not provided, the currently selected cell or range will be used as the paste destination. | @@ -499,14 +511,23 @@ To paste content into a specific sheet, include the target sheet name along with ## Events -The Syncfusion Blazor Spreadsheet provides two events that are triggered during the clipboard action such as [CutCopyActionBegin](https://help.syncfusion.com/cr/blazor/Syncfusion.Blazor.Spreadsheet.CutCopyActionBeginEventArgs.html) and [Pasting](https://help.syncfusion.com/cr/blazor/Syncfusion.Blazor.Spreadsheet.PastingEventArgs.html). These events can be used to perform any custom actions before the clipboard action starts. +The Blazor Spreadsheet provides events that are triggered during the clipboard action such as [CutCopyActionBegin](https://help.syncfusion.com/cr/blazor/Syncfusion.Blazor.Spreadsheet.CutCopyActionBeginEventArgs.html) and [Pasting](https://help.syncfusion.com/cr/blazor/Syncfusion.Blazor.Spreadsheet.PastingEventArgs.html). These events can be used to perform any custom actions before the clipboard action starts or interacted with, allowing for validation, customization, and response handling. * **CutCopyActionBegin** - [CutCopyActionBegin](https://help.syncfusion.com/cr/blazor/Syncfusion.Blazor.Spreadsheet.CutCopyActionBeginEventArgs.html) event is triggered before a cut or copy operation begins. * **Pasting** - [Pasting](https://help.syncfusion.com/cr/blazor/Syncfusion.Blazor.Spreadsheet.PastingEventArgs.html) event is triggered before a paste operation begins. -**CutCopyActionBegin Event** +**CutCopyActionBegin** -The `CutCopyActionBegin` event is triggered before a cut or copy operation begins. This event provides details about the operation and allows for cancellation if required. +The `CutCopyActionBegin` event is triggered before a copy or cut operation is performed in the spreadsheet. This event provides an opportunity to inspect, validate, or cancel the operation based on custom business logic + +**Purpose** + +This event serves various scenarios where clipboard operations need monitoring or restriction: + +* Preventing sensitive data from being copied +* Logging clipboard operations for audit purposes +* Implementing custom validation rules for specific cells or ranges +* Restricting cut operations while allowing copy operations **Event Arguments** @@ -549,9 +570,18 @@ The `CutCopyActionBeginEventArgs` includes the following properties: {% endhighlight %} {% endtabs %} -**Pasting Event** +**Pasting** + +The `Pasting` event is triggered before data is pasted into the spreadsheet. This event allows inspection and validation of the paste operation before it is completed, with options to modify or cancel the operation entirely. + +**Purpose** + +This event is valuable for scenarios requiring paste operation control: -The `Pasting` event is triggered before a paste operation begins. It provides information about the paste operation and allows you to validate or cancel it. +* Validating data before allowing it to be pasted +* Restricting paste operations to specific sheets or ranges +* Implementing data transformation rules during paste operations +* Maintaining data integrity through paste operation oversight **Event Arguments** From 44c89cd50e9b6a082922b0af421c372d8d59c7e3 Mon Sep 17 00:00:00 2001 From: Adithyan29 Date: Mon, 28 Jul 2025 12:12:53 +0530 Subject: [PATCH 3/3] 971536: Updated the content for clipboard --- blazor/spreadsheet/clipboard.md | 197 +++++++++++++++----------------- 1 file changed, 93 insertions(+), 104 deletions(-) diff --git a/blazor/spreadsheet/clipboard.md b/blazor/spreadsheet/clipboard.md index b2f13d9947..3417bebfda 100644 --- a/blazor/spreadsheet/clipboard.md +++ b/blazor/spreadsheet/clipboard.md @@ -11,27 +11,29 @@ documentation: ug The Spreadsheet supports clipboard operations such as **Cut**, **Copy**, and **Paste**. These operations can be enabled or disabled using the [EnableClipboard](https://help.syncfusion.com/cr/blazor/Syncfusion.Blazor.Spreadsheet.SfSpreadsheet.html#Syncfusion_Blazor_Spreadsheet_SfSpreadsheet_EnableClipboard) property of the Spreadsheet component. By default, the `EnableClipboard` property is set to **true**. -N> When `EnableClipboard` is set to **false**, the **Cut** and **Copy** options are removed from the user interface (Ribbon and Context Menu). In addition, shortcut keys (**Ctrl+C, Ctrl+X, Ctrl+V**) and API methods will not work. +The keyboard shortcuts are available to perform clipboard operations efficiently within the Spreadsheet component. `Ctrl+C` copies the selected cells, `Ctrl+X` cuts the selected cells, and `Ctrl+V` pastes the content from the clipboard. + +When `EnableClipboard` is set to **false**, the **Cut** and **Copy** options are removed from the user interface (Ribbon and Context Menu). In addition, shortcut keys (**Ctrl+C, Ctrl+X, Ctrl+V**) and API methods will not work. If the worksheet is protected, clipboard operations such as cut and paste are also disabled. For more information on worksheet protection, refer [here](https://blazor.syncfusion.com/documentation/spreadsheet/protection#protect-sheet). ## Cut -The cut operation removes data from selected cells, rows, or columns in a sheet and temporarily stores it on the clipboard for use elsewhere. Once pasted to a new location, the original content is removed, effectively allowing users to move data within the spreadsheet. +The **Cut** operation removes data from selected cells, rows, or columns within a worksheet and temporarily stores the content on the clipboard. When the content is pasted to a new location, the original data is deleted from its source. This behavior enables the relocation of content within the Spreadsheet. ### Cut operations via UI -The cut operation can be performed through the user interface (UI) using any of the following methods: +The **Cut** operation can be performed through the user interface (UI) using any of the following methods: **Using the Ribbon** - Select a cell or range of cells to cut the content. -- Click the **Cut** button in the **Home** tab of the **Ribbon** toolbar. This will cut the selected cell or range. +- Click the **Cut** button in the **Home** tab of the **Ribbon** toolbar. This action removes the selected cell or range of cells and places the content on the clipboard. ![Cut - Ribbon](images/cut-copy.png) **Using the Context Menu** - Select a cell or range of cells to cut the content. -- Right-click on the selected cell or range. +- Right-click on the selected cell or range of cells. - Choose the **Cut** option from the context menu. ![Cut - Context Menu](images/contextmenu-cut-copy.png) @@ -40,11 +42,11 @@ The cut operation can be performed through the user interface (UI) using any of The [CutCellAsync](https://help.syncfusion.com/cr/blazor/Syncfusion.Blazor.Spreadsheet.SfSpreadsheet.html#Syncfusion_Blazor_Spreadsheet_SfSpreadsheet_CutCellAsync_System_String_) method allows performing cut operations within any sheet. This method copies the specified cell or range and its properties (including value, format, style, etc.) to the clipboard and removes it from the sheet. It supports multiple scenarios for cutting cells or ranges. Below are the details for each scenario, including code examples and parameter information. -> The cut operation will not execute if invalid or out-of-boundary cell ranges are provided. Ensure that all cell addresses fall within the valid worksheet boundaries. +> The **Cut** operation will not execute if invalid or out-of-boundary cell ranges are specified. All cell references must fall within the defined worksheet boundaries to ensure successful execution of the operation. **Cut active range** -When [CutCellAsync](https://help.syncfusion.com/cr/blazor/Syncfusion.Blazor.Spreadsheet.SfSpreadsheet.html#Syncfusion_Blazor_Spreadsheet_SfSpreadsheet_CutCellAsync_System_String_) method is called without any parameters, it automatically cuts the content from the last selected range if an active selection exists. If no range is currently selected, it cuts the active cell. +When `CutCellAsync` method is invoked without any parameters, the content is automatically cut from the most recently selected range, provided an active selection exists. If no range is currently selected, the method defaults to cutting the content from the active cell. {% tabs %} {% highlight razor %} @@ -69,7 +71,7 @@ When [CutCellAsync](https://help.syncfusion.com/cr/blazor/Syncfusion.Blazor.Spre public async Task CutActiveCell() { - // To cut from the current cell. + // Cuts content from the currently active cell or selected range in the active worksheet. await SpreadsheetInstance.CutCellAsync(); } } @@ -79,13 +81,13 @@ When [CutCellAsync](https://help.syncfusion.com/cr/blazor/Syncfusion.Blazor.Spre **Cut specific range in active sheet** -To cut content from specific cells in the active sheet, provide cell address as a parameter to the `CutCellAsync` method. When you specify a cell or range, the Spreadsheet component will cut that content and place it on the clipboard, ready for pasting elsewhere. +To cut content from specific cells in the active worksheet, a cell address or a range of cell addresses must be passed as a parameter to the `CutCellAsync` method. When a valid cell or range is specified, the Spreadsheet component cuts the corresponding content and places it on the clipboard, making it available for pasting in another location. The available parameters in the `CutCellAsync` method are: | Parameter | Type | Description | |-------------|-------------------|-------------| -| cellAddress | string (optional) | Specifies which cell(s) to cut. Accepts either a single cell reference (e.g., `"A1"`) or a range (e.g., `"A1:B5"`) from the active sheet. If not provided, the currently selected cell or range will be cut. | +| cellAddress | string (optional) | Specifies the target cell or range of cells to be cut. Accepts either a single cell reference (for example, **"A1"**) or a range (for example, **"A1:B5"**) from the active worksheet. If no parameter is provided, the currently selected cell or range will be used for the **Cut** operation. | {% tabs %} {% highlight razor %} @@ -111,13 +113,13 @@ The available parameters in the `CutCellAsync` method are: public async Task CutCell() { - // To cut the specified cell. + // Cuts the specified cell from the active worksheet. await SpreadsheetInstance.CutCellAsync("A2"); } public async Task CutRange() { - // To cut a range of cells. + // Cuts a specified range of cells from the active worksheet. await SpreadsheetInstance.CutCellAsync("A1:D10"); } } @@ -127,13 +129,13 @@ The available parameters in the `CutCellAsync` method are: **Cut specific range in different sheet** -To cut content from a specific sheet, include the source sheet name along with the cell reference in the parameter to the `CutCellAsync` method. When specifying a sheet name, use an exclamation mark (`!`) to separate it from the cell reference, and the Spreadsheet component will cut that content and place it on the clipboard, ready for pasting elsewhere. +To cut content from a specific worksheet, the source sheet name must be included along with the cell reference in the parameter passed to the `CutCellAsync` method. When specifying a sheet name, an exclamation mark (**!**) must be used to separate the sheet name from the cell reference. Upon execution, the Spreadsheet component cuts the designated content and places it on the clipboard, making it available for pasting in another location. The available parameters in the `CutCellAsync` method are: | Parameter | Type | Description | |-------------|-------------------|-------------| -| cellAddress | string (optional) | Specifies which cell(s) to cut. Accepts either a single cell reference (e.g., `"Sheet1!A1"`) or a range (e.g., `"Sheet2!A1:C5"`) from a specific sheet. If not provided, the currently selected cell or range will be cut. | +| cellAddress | string (optional) | Specifies the cell or range of cells to be cut. Accepts either a single cell reference (for example, **"Sheet1!A1"**) or a range (for example, **"Sheet2!A1:C5"**) from a specific worksheet. If no parameter is provided, the currently selected cell or range from the active worksheet will be used for the cut operation. | {% tabs %} {% highlight razor %} @@ -159,13 +161,14 @@ The available parameters in the `CutCellAsync` method are: public async Task CutCellFromSpecificSheet() { - // The address, along with the sheet name, to be cut. + + // Specifies the address, along with the worksheet name, from which the content will be cut. await SpreadsheetInstance.CutCellAsync("Sheet1!B2"); } public async Task CutRangeFromSpecificSheet() { - // To cut a range from a specific sheet. + // Cuts a specified range from a specific worksheet. await SpreadsheetInstance.CutCellAsync("Sheet2!B3:E8"); } } @@ -175,7 +178,7 @@ The available parameters in the `CutCellAsync` method are: ## Copy -The copy operation duplicates data from a selected range of cells, rows, or columns within a sheet and temporarily stores it on the clipboard for use elsewhere. Unlike the **Cut** operation, copying retains the original content in its location. +The **Copy** operation duplicates data from a selected range of cells, rows, or columns within a worksheet and temporarily stores it on the clipboard. Unlike the **Cut** operation, copying retains the original content in its source location, allowing the data to be reused without modification. ### Copy operations via UI @@ -183,28 +186,28 @@ The copy operation can be performed through the user interface (UI) using any of **Using the Ribbon** -- Select the cell or range to copy. -- Click the **Copy** button in the **Home** tab of the **Ribbon** toolbar. This will copy the current active cell or range. +- Select the cell or range of cells to copy. +- Click the **Copy** button in the **Home** tab of the **Ribbon** toolbar. This action duplicates the selected cell or range of cells and places the content on the clipboard. ![Copy - Ribbon](images/cut-copy.png) **Using the Context Menu** -- Select the cell or range to copy. -- Right-click on the selected cell or range. +- Select the cell or range of cells to copy. +- Right-click on the selected cell or range of cells. - Choose the **Copy** option from the context menu. ![Copy - Context Menu](images/contextmenu-cut-copy.png) ### Copy operations programmatically -The [CopyCellAsync](https://help.syncfusion.com/cr/blazor/Syncfusion.Blazor.Spreadsheet.SfSpreadsheet.html#Syncfusion_Blazor_Spreadsheet_SfSpreadsheet_CopyCellAsync_System_String_) method enables performing copy operations within any sheet. This method copies the specified cell or range along with its properties (including value, format, style, etc.) to the clipboard. It supports multiple scenarios for copying cells or ranges. Below are the details for each scenario, including code examples and parameter information. +The [CopyCellAsync](https://help.syncfusion.com/cr/blazor/Syncfusion.Blazor.Spreadsheet.SfSpreadsheet.html#Syncfusion_Blazor_Spreadsheet_SfSpreadsheet_CopyCellAsync_System_String_) method enables performing copy operations within any sheet. This method copies the specified cell or range of cells along with its properties (including value, format, style, etc.) to the clipboard. It supports multiple scenarios for copying cells or ranges. Below are the details for each scenario, including code examples and parameter information. -> The copy operation will not execute if invalid or out-of-boundary cell ranges are provided. Ensure that all cell addresses fall within the valid worksheet boundaries. +> The **Copy** operation will not execute if invalid or out-of-boundary cell ranges are specified. All cell addresses must fall within the valid boundaries of the worksheet to ensure successful execution of the operation. **Copy active range** -When [CopyCellAsync](https://help.syncfusion.com/cr/blazor/Syncfusion.Blazor.Spreadsheet.SfSpreadsheet.html#Syncfusion_Blazor_Spreadsheet_SfSpreadsheet_CopyCellAsync_System_String_) method is called without any parameters, the method automatically copies the content from the last selected range if an active selection exists. If no range is selected, it copies the active cell. +When `CopyCellAsync` method is invoked without any parameters, the content is automatically copied from the most recently selected range, provided an active selection exists. If no range is selected, the method defaults to copying the content from the active cell. {% tabs %} {% highlight razor %} @@ -229,7 +232,7 @@ When [CopyCellAsync](https://help.syncfusion.com/cr/blazor/Syncfusion.Blazor.Spr public async Task CopyActiveCell() { - // To copy from the current cell. + // Copies content from the currently active cell or selected range in the active worksheet. await SpreadsheetInstance.CopyCellAsync(); } } @@ -239,13 +242,13 @@ When [CopyCellAsync](https://help.syncfusion.com/cr/blazor/Syncfusion.Blazor.Spr **Copy specific range in active sheet** -To copy content from specific cells in the active sheet, provide cell address as a parameter to the `CopyCellAsync` method. When you specify a cell or range, the Spreadsheet component will copy that content and place it on the clipboard, ready for pasting elsewhere. +To copy content from specific cells in the active worksheet, a cell address or a range of cell addresses must be provided as a parameter to the `CopyCellAsync` method. When a valid cell or range is specified, the Spreadsheet component copies the corresponding content and places it on the clipboard, making it available for pasting in another location. The available parameters in the `CopyCellAsync` method are: | Parameter | Type | Description | |-------------|-------------------|-------------| -| cellAddress | string (optional) | Specifies which cell(s) to copy. Accepts either a single cell from the active sheet (e.g., `"A1"`) or a cell range (e.g., `"A1:B5"`). If not provided, the currently selected cell or range will be copied. | +| cellAddress | string (optional) | Specifies the cell or range of cells to be copied. Accepts either a single cell reference from the active worksheet (for example, **"A1"**) or a range (for example, **"A1:B5"**). If no parameter is provided, the currently selected cell or range will be used for the copy operation. | {% tabs %} {% highlight razor %} @@ -271,13 +274,13 @@ The available parameters in the `CopyCellAsync` method are: public async Task CopyCell() { - // To copy the specified cell. + // The specified cell is copied from the active worksheet. await SpreadsheetInstance.CopyCellAsync("A2"); } public async Task CopyRange() { - // To copy a range of cells. + // A specified range of cells is copied from the active worksheet. await SpreadsheetInstance.CopyCellAsync("A1:D10"); } } @@ -287,13 +290,13 @@ The available parameters in the `CopyCellAsync` method are: **Copy specific range in different sheet** -To copy content from a specific sheet, include the source sheet name along with the cell reference in the parameter to the `CopyCellAsync` method. When specifying a sheet name, use an exclamation mark (`!`) to separate it from the cell reference, and the Spreadsheet component will copy that content and place it on the clipboard, ready for pasting elsewhere. +To copy content from a specific worksheet, the source sheet name must be included along with the cell reference in the parameter passed to the `CopyCellAsync` method. When specifying the sheet name, an exclamation mark (**!**) is used to separate it from the cell reference. The Spreadsheet component performs the copy operation and places the content on the clipboard, making it available for pasting into another location. The available parameters in the `CopyCellAsync` method are: | Parameter | Type | Description | |-------------|-------------------|-------------| -| cellAddress | string (optional) | Specifies which cell(s) to copy. Accepts either a single cell from a specific sheet (e.g., `"Sheet1!A1"`) or a cell range (e.g., `"Sheet2!A1:C5"`). If not provided, the currently selected cell or range will be copied. | +| cellAddress | string (optional) | Specifies the cell or range of cells to be copied. Accepts either a single cell reference from a specific worksheet (for example, **"Sheet1!A1"**) or a range of cells (for example, **"Sheet2!A1:C5"**). If no value is provided, the currently selected cell or range from the active worksheet will be used for the copy operation. | {% tabs %} {% highlight razor %} @@ -319,13 +322,13 @@ The available parameters in the `CopyCellAsync` method are: public async Task CopyCellFromSpecificSheet() { - // The address, along with the sheet name, to be copied. + // The cell address, including the sheet name, is copied from the specified worksheet. await SpreadsheetInstance.CopyCellAsync("Sheet1!B2"); } public async Task CopyRangeFromSpecificSheet() { - // To copy a range from a specific sheet. + // A specified range of cells is copied from the designated worksheet. await SpreadsheetInstance.CopyCellAsync("Sheet2!B3:E8"); } } @@ -337,7 +340,7 @@ The available parameters in the `CopyCellAsync` method are: The paste operation inserts data from the clipboard into a selected range of cells, rows, or columns, retaining all relevant details such as values, formats, and styles. When performing a **Cut** followed by **Paste**, the clipboard is cleared after the data is transferred. In contrast, with a **Copy** followed by **Paste**, the clipboard contents remain available for reuse. -External clipboard support is also provided, enabling users to paste content not only from within the spreadsheet but also from outside sources such as Google Sheets, Microsoft Excel, Word documents, plain text files, and web pages. +**External clipboard** support is provided, allowing content to be pasted not only from within the spreadsheet but also from external sources such as Google Sheets, Microsoft Excel, Word documents, plain text files, and web pages. ### Paste operations via UI @@ -345,27 +348,37 @@ The paste operation can be performed through the user interface (UI) using any o **Using the Ribbon** -- Select a range of cells or click on a cell. -- Click the **Paste** button in the **Home** tab of the **Ribbon** toolbar. This will paste the values that were cut or copied from the clipboard into the selected range. If no values are on the clipboard, the **Paste** option will be disabled. +- A cell must be selected or a range of cells highlighted before initiating the paste operation. +- The **Paste** button located in the **Home** tab of the **Ribbon** toolbar must be clicked to perform the paste action. +- The values previously cut or copied from the clipboard will be inserted into the selected range. +- If the clipboard does not contain any values, the **Paste** option will remain disabled. ![Paste - Ribbon](./images/cutcopypaste.png) **Using the Context Menu** -- Select a range of cells or click on a cell. -- Right-click and choose the **Paste** option from the context menu. If no values are on the clipboard, the **Paste** option will be disabled. +- A cell must be clicked or a range of cells selected before initiating the paste operation. +- The **Paste** option must be selected from the context menu accessed via right-click. +- The values previously cut or copied from the clipboard will be inserted into the selected range. +- If the clipboard does not contain any values, the **Paste** option will remain disabled. ![Paste - Context Menu](./images/contextcutcopypaste.png) ### Paste operations programmatically -The [PasteCellAsync](https://help.syncfusion.com/cr/blazor/Syncfusion.Blazor.Spreadsheet.SfSpreadsheet.html#Syncfusion_Blazor_Spreadsheet_SfSpreadsheet_PasteCellAsync_System_String_) method pastes the clipboard content into a specified cell or range and preserves all associated properties (including value, format, style, etc.). +The [PasteCellAsync](https://help.syncfusion.com/cr/blazor/Syncfusion.Blazor.Spreadsheet.SfSpreadsheet.html#Syncfusion_Blazor_Spreadsheet_SfSpreadsheet_PasteCellAsync_System_String_) method pastes the clipboard content into a specified cell or range of cells and preserves all associated properties (including value, format, style, etc.). When the source range is larger than the specified target range, all data from the source will still be pasted. The paste operation automatically extends beyond the defined target boundaries and overrides the content in the expanded area to match the full dimensions of the source. + +**Example** +- Source Range: **"Sheet1!A1:C3"** (3 rows × 3 columns) +- Target Range: **"Sheet2!B2"** (single cell) + +In this case, although only a single cell is selected as the target, the paste operation overrides the range **"Sheet2!B2:D4"** to match the full 3×3 source content. -> The paste operation will not execute if invalid or out-of-boundary cell ranges are provided. Ensure that all cell addresses fall within the valid worksheet boundaries. +> The **Paste** operation will not be executed if invalid or out-of-boundary cell ranges are specified. All cell addresses must fall within the valid boundaries of the worksheet to ensure successful execution of the paste action. **Paste to active range** -When [PasteCellAsync](https://help.syncfusion.com/cr/blazor/Syncfusion.Blazor.Spreadsheet.SfSpreadsheet.html#Syncfusion_Blazor_Spreadsheet_SfSpreadsheet_PasteCellAsync_System_String_) method is called without any parameters, it automatically pastes the content to the last selected range if an active selection exists. If no range is selected, it pastes to the active cell. +When the `PasteCellAsync` method is invoked without any parameters, the content is automatically pasted into the last selected range, provided an active selection exists. If no range is selected, the content is pasted into the active cell. {% tabs %} {% highlight razor %} @@ -390,7 +403,7 @@ When [PasteCellAsync](https://help.syncfusion.com/cr/blazor/Syncfusion.Blazor.Sp public async Task PasteActiveCell() { - // To paste to the current cell. + // The content is pasted into the currently active cell or range. await SpreadsheetInstance.PasteCellAsync(); } } @@ -400,13 +413,13 @@ When [PasteCellAsync](https://help.syncfusion.com/cr/blazor/Syncfusion.Blazor.Sp **Paste to specific range in active sheet** -To paste content into specific range in the current active sheet, provide the target cell address as a parameter to the `PasteCellAsync` method. You can specify either a single cell or a range of cells as the destination. When the source range (copied content) is larger than the specified target range, all data from the source will still be pasted, automatically extending beyond the specified target boundaries to accommodate all content. +To paste content into specific range in the current active sheet, provide the target cell address as a parameter to the `PasteCellAsync` method. A valid cell selection must exist prior to executing the paste operation. Either a single cell or a range of cells can be specified as the destination. The available parameters in the `PasteCellAsync` method are: | Parameter | Type | Description | |-------------|-------------------|-------------| -| cellAddress | string (optional) | Specifies the target cell(s) for pasting clipboard content. Accepts either a single cell (e.g., `"A1"`) or a cell range (e.g., `"A1:B5"`) from the active sheet. If not provided, the currently selected cell or range will be used as the paste destination. | +| cellAddress | string (optional) | Specifies the target cell or range of cells for pasting clipboard content. Accepts either a single cell reference (for example, **"A1"**) or a range of cells (for example, **"A1:B5"**) from the active worksheet. A valid cell selection must exist prior to executing the paste operation. If no parameter is provided, the currently selected cell or range will be used as the paste destination. | {% tabs %} {% highlight razor %} @@ -415,7 +428,7 @@ The available parameters in the `PasteCellAsync` method are: - + @@ -433,23 +446,23 @@ The available parameters in the `PasteCellAsync` method are: public async Task PasteCell() { - // To paste to the specified cell. + // The clipboard content is pasted into the specified cell. await SpreadsheetInstance.PasteCellAsync("A2"); } public async Task PasteRange() { - // To paste to the specified range. + // The clipboard content is pasted into the specified range of cells. await SpreadsheetInstance.PasteCellAsync("A2:B5"); } - // Copy a large range and paste to smaller range. - public async Task CopyLargerRangeThanTarget() + // A larger source range is copied and pasted into a smaller target range. + public async Task CopyAndPasteOversizedRange() { - // Copy a 7-row range. + // A range containing 7 rows is copied from the source. await SpreadsheetInstance.CopyCellAsync("F3:F9"); - // Paste to a smaller 3-row range. All 7 rows will be pasted, extending beyond the specified range. + // The content is pasted into a smaller 3-row target range. All 7 rows will be pasted, extending beyond the specified range. await SpreadsheetInstance.PasteCellAsync("A5:A7"); } } @@ -459,21 +472,20 @@ The available parameters in the `PasteCellAsync` method are: **Paste to specific range in different sheet** -To paste content into a specific sheet, include the target sheet name along with the cell reference as a parameter to the `PasteCellAsync` method. When specifying a sheet name, use an exclamation mark (!) to separate it from the cell reference. When the source range (copied content) is larger than the specified target range, all data will still be pasted completely, extending beyond the specified target boundaries to accommodate all content. +To paste content into a specific sheet, include the target sheet name along with the cell reference as a parameter to the `PasteCellAsync` method. When specifying a sheet name, use an exclamation mark (**!**) to separate it from the cell reference. The available parameters in the `PasteCellAsync` method are: | Parameter | Type | Description | |-------------|-------------------|-------------| -| cellAddress | string (optional) | Specifies the target cell(s) for pasting clipboard content. Accepts either a single cell from a specific sheet (e.g., `"Sheet1!A1"`) or a cell range (e.g., `"Sheet2!A1:C5"`). If not provided, the currently selected cell or range will be used as the paste destination. | +| cellAddress | string (optional) | Specifies the target cell or range of cells for pasting clipboard content. Accepts either a single cell reference from a specific worksheet (for example, **"Sheet1!A1"**) or a range of cells (for example, **"Sheet2!A1:C5"**). A valid cell selection must exist before executing the paste operation. If no parameter is provided, the currently selected cell or range will be used as the paste destination. | {% tabs %} {% highlight razor %} @using Syncfusion.Blazor.Spreadsheet - - + @@ -489,21 +501,11 @@ The available parameters in the `PasteCellAsync` method are: DataSourceBytes = File.ReadAllBytes(filePath); } - public async Task CopyPasteCellBetweenSheets() + public async Task PasteCellToTargetSheet() { - // The address, along with the sheet name, to be pasted. + // The cell address, including the sheet name, is used as the paste destination await SpreadsheetInstance.PasteCellAsync("Sheet1!B2"); - } - - // Copy from one sheet and paste to another without switching sheets. - public async Task CopyPasteRangeBetweenSheets() - { - // Copy value from "Sheet1". - await SpreadsheetInstance.CopyCellAsync("Sheet1!A1:A5"); - - // Paste to "Sheet2" without switching to it. - await SpreadsheetInstance.PasteCellAsync("Sheet2!C3"); - } + } } {% endhighlight %} @@ -513,22 +515,16 @@ The available parameters in the `PasteCellAsync` method are: The Blazor Spreadsheet provides events that are triggered during the clipboard action such as [CutCopyActionBegin](https://help.syncfusion.com/cr/blazor/Syncfusion.Blazor.Spreadsheet.CutCopyActionBeginEventArgs.html) and [Pasting](https://help.syncfusion.com/cr/blazor/Syncfusion.Blazor.Spreadsheet.PastingEventArgs.html). These events can be used to perform any custom actions before the clipboard action starts or interacted with, allowing for validation, customization, and response handling. -* **CutCopyActionBegin** - [CutCopyActionBegin](https://help.syncfusion.com/cr/blazor/Syncfusion.Blazor.Spreadsheet.CutCopyActionBeginEventArgs.html) event is triggered before a cut or copy operation begins. -* **Pasting** - [Pasting](https://help.syncfusion.com/cr/blazor/Syncfusion.Blazor.Spreadsheet.PastingEventArgs.html) event is triggered before a paste operation begins. +* **CutCopyActionBegin** - `CutCopyActionBegin` event is triggered before a cut or copy operation is initiated. +* **Pasting** - `Pasting` event is triggered prior to the initiation of a paste operation. -**CutCopyActionBegin** +### CutCopyActionBegin -The `CutCopyActionBegin` event is triggered before a copy or cut operation is performed in the spreadsheet. This event provides an opportunity to inspect, validate, or cancel the operation based on custom business logic +The `CutCopyActionBegin` event is triggered before a copy or cut operation is performed in the spreadsheet. This event allows inspection, validation, or cancellation of the operation based on custom business logic. **Purpose** -This event serves various scenarios where clipboard operations need monitoring or restriction: - -* Preventing sensitive data from being copied -* Logging clipboard operations for audit purposes -* Implementing custom validation rules for specific cells or ranges -* Restricting cut operations while allowing copy operations - +This event addresses scenarios that require monitoring or restriction of clipboard operations, such as preventing sensitive data from being copied, logging clipboard activities for audit and compliance purposes, enforcing custom validation rules for designated cells or ranges, and restricting cut operations while allowing copy functionality. **Event Arguments** @@ -536,24 +532,23 @@ The `CutCopyActionBeginEventArgs` includes the following properties: | Event Arguments | Description | |----------------|-------------| -| Action | An enum value from the ClipboardAction class that indicates whether the operation is `ClipboardAction.Cut` or `ClipboardAction.Copy`. | -| CopiedRange | A string representing the range being copied, including the sheet name (e.g., "Sheet1!A1:B5"). | -| Cancel | A boolean value that can be set to true to prevent the operation. | +| ClipboardAction | Specifies the type of clipboard operation in progress. Returns a value from the **ClipboardAction** enumeration, such as **ClipboardAction.Cut** or **ClipboardAction.Copy**. | +| CopiedRange | Represents the full address of the cell range involved in the clipboard operation. Includes the worksheet name and range in A1 notation (e.g., **"Sheet1!A1:B5"**). | +| Cancel | Indicates whether the clipboard operation should be cancelled. Set to **true** to prevent the cut or copy action from proceeding. | {% tabs %} {% highlight razor tabtitle="Index.razor" %} @using Syncfusion.Blazor.Spreadsheet - + @code { public byte[] DataSourceBytes { get; set; } - public SfSpreadsheet SpreadsheetInstance { get; set; } - + protected override void OnInitialized() { string filePath = "wwwroot/Sample.xlsx"; @@ -562,7 +557,7 @@ The `CutCopyActionBeginEventArgs` includes the following properties: public void OnCutCopyActionBegin(CutCopyActionBeginEventArgs args) { - // To cancel the cut or copy action. + // Cancels the cut or copy operation. args.Cancel = true; } } @@ -570,18 +565,13 @@ The `CutCopyActionBeginEventArgs` includes the following properties: {% endhighlight %} {% endtabs %} -**Pasting** +### Pasting The `Pasting` event is triggered before data is pasted into the spreadsheet. This event allows inspection and validation of the paste operation before it is completed, with options to modify or cancel the operation entirely. **Purpose** -This event is valuable for scenarios requiring paste operation control: - -* Validating data before allowing it to be pasted -* Restricting paste operations to specific sheets or ranges -* Implementing data transformation rules during paste operations -* Maintaining data integrity through paste operation oversight +This event is applicable in scenarios that require control over paste operations, such as validating data before allowing paste actions, restricting paste functionality to specific worksheets or cell ranges, applying data transformation rules during paste execution, and enforcing data integrity through oversight of paste operations. **Event Arguments** @@ -589,24 +579,23 @@ The `PastingEventArgs` includes the following properties: | Event Arguments | Description | |----------------|-------------| -| ExternalClipboardData | An array of strings containing raw text data from external sources (like Excel or Google Sheets), with each element representing a row of data. Set to null when copying from within the workbook. | -| CopiedRange | A string in the format "SheetName!Range" (e.g., "Sheet1!A1:A10") representing the source location of the copied or cut content. Set to null when pasting external content. | -| PasteRange | A string in the format "SheetName!Range" specifying the target cell range where content will be pasted. | -| Cancel | A boolean value that can be set to true to prevent the paste operation, allowing event handlers to control the paste behavior. The default value is false. | +| ExternalClipboardData | An array of strings containing raw text data from external sources (like Excel or Google Sheets), with each element representing a row of data. Set to **null** when copying from within the workbook. | +| CopiedRange | A string in the format **"SheetName!Range"** (e.g., **"Sheet1!A1:A10"**) representing the source location of the copied or cut content. Set to **null** when pasting external content. | +| PasteRange | A string in the format **"SheetName!Range"** specifying the target cell range where content will be pasted. | +| Cancel | A boolean value that can be set to **true** to prevent the paste operation, allowing event handlers to control the paste behavior. The default value is **false**. | {% tabs %} {% highlight razor tabtitle="Index.razor" %} @using Syncfusion.Blazor.Spreadsheet - + - + @code { - public byte[] DataSourceBytes { get; set; } - public SfSpreadsheet SpreadsheetInstance { get; set; } + public byte[] DataSourceBytes { get; set; } protected override void OnInitialized() { @@ -614,15 +603,15 @@ The `PastingEventArgs` includes the following properties: DataSourceBytes = File.ReadAllBytes(filePath); } - public void OnBeforePaste(PastingEventArgs args) + public void OnPasting(PastingEventArgs args) { - // Prevent pasting into a specific range + // Cancels the paste operation if the target range includes "A1:B5". if (args.PasteRange.Contains("A1:B5")) { args.Cancel = true; } - // Validate external content + // Checks external clipboard data for restricted content. if (args.ExternalClipboardData != null) { foreach (var line in args.ExternalClipboardData)