I'm using SpreadProcessing in conjunction with a Blazor TelerikSpreadsheet component and I've found that when I copy a cell from any Excel file and paste that into any cell in the TelerikSpreadsheet and then subsequently call XlsxFormatProvider.Import(), it throws an exception with the following message:
Not supported from value: start
I've attached a sample project to demonstrate the issue.
How can I successfully paste from Excel and then call XlsxFormatProvider.Import()?
I'm using SpreadProcessing in conjunction with a Blazor TelerikSpreadsheet component, and as I understand it from the documentation, if I want to mark certain cells as read only, the way to do that is by protecting the worksheet and then unlocking the cells I want to be editable. In my use case I need to disable the cells in the first row but leave all other cells editable and I've encountered two issues.
First, if I set up a loop to spin through the rows (other than the fist row) and mark them as unlocked, as such:
for (var i = 1; i < worksheet.Rows.Count; i++)
{
worksheet.Rows[i].SetIsLocked(false);
}
The first issue is that worksheet.Rows.Count returns 1,048,576 rows. By default the spreadsheet displays 200 rows. I don't know if that default is on the Blazor side and that it only displays 200 of the 1,048,576 rows that are actually in the worksheet or what, but it's not really reasonable to spin through all those rows attempting to unlock them when they're not even visible. So that's issue number 1.
Issue number 2 is, calling SetIsLocked(false) on each row doesn't actually unlock the row. It has no effect. However I've found that if I call SetIsLocked(false) on a column, the column does get unlocked but if I then try to lock the cell in the first row of that column it doesn't get locked. So it's like the unlock of the column overrides the lock of the individual cell in that column. The only way I've been able to get this to work is as such:
for (var i = 1; i < 199; i++)
{
for (int j = 0; j < columnTitles.Count; j++)
{
worksheet.Cells[i, j].SetIsLocked(false);
}
}
columnTitles is my list of column headers so I'm really only enabling the cells under the column headers I've added and not the complete row, but that's fine. But I've had to hardcode the highest row index of 199. Again, I don't know where that default comes from but it's not good to hardcode that index because it could always change in a future version.
So my question is, is there a better, more efficient way to lock the first row but unlock all other rows?
I'm using SpreadProcessing in conjunction with a TelerikSpreadsheet in a Blazor app where the user can modify a spreadsheet and click a submit button. In my submit handler I'm using the result of Worksheet.UsedCellRange to set up my loops for the purpose of validation. When the user clicks submit, I get the expected result from Worksheet.UsedCellRange and then I spin the used rows and columns and apply validation. If there are validation errors I make the cell red and then export the workbook back to a memory stream and assign the byte array back to the variable to which the spreadsheet is bound. That works fine.
The issue I'm having is that if the user clicks submit, gets validation errors, makes a change and then clicks the submit button a second time, the result I get from Worksheet.UsedCellRange includes all rows, even if only one or two rows actually have data. To narrow down the issue I removed all my validation logic so I am not making any changes to the cells before I assign the byte array, but the second time through the result of UsedCellRange still reports all rows. Am I not assigning the byte array correctly at the end of my submit method? See code:
private async Task OnSubmitAsync()
{
byte[] sheet = await _spreadsheetRef.ExportToExcelAsync();
using MemoryStream ms = new(sheet);
XlsxFormatProvider formatProvider = new();
Workbook workbook = formatProvider.Import(ms, new TimeSpan(0, 0, 5));
Worksheet worksheet = workbook.Worksheets.First();
// The first time through this is correct, second time through it reports all 200 rows are in use. Why?
CellRange cellRange = worksheet.UsedCellRange;
// Validation logic would normally go here
// Set the byte array back to the bound variable
// Should I be doing this differently?
ms.SetLength(0);
formatProvider.Export(workbook, ms, new TimeSpan(0, 0, 30));
_fileData = ms.ToArray(); // _fileData is bound to the TelerikSpreadsheet component
}
I've seen a couple other posts here about export performance, but they both refer to relatively large amounts of data. I am having issues so I stripped my example down to the where it's exporting a blank spreadsheet (see code below) but it still takes over 10 seconds running in debug on my laptop. I'm using this in the context of a Blazor app and since this is synchronous the page hangs while the export is running. What can I do to speed this up?
Workbook workbook = new Workbook();
Worksheet worksheet = workbook.Worksheets.Add();
IWorkbookFormatProvider formatProvider = new XlsxFormatProvider();
using MemoryStream ms = new();
formatProvider.Export(workbook, ms, new TimeSpan(0, 0, 30)); // This takes over 10 seconds
_fileData = ms.ToArray(); // byte array that the Blazor component reads
We need to print a GridView and are implementing the code found in "GridView | Print and Print Preview" example in the WPF Desktop Examples 2024 Q4 app but are encountering two issues also present in the Telerik-provided example.
1) Changes made in Print Preview are not carried over when the Print button is pressed. For example, if you change to Landscape/Legal in Print Preview, this will revert back to Portrait/Letter when Print is clicked.
2) Clicking Print on the Print Preview window shoves the Print Preview window to the background and if Cancel is clicked on the Print window, the user has to Alt-Tab through windows to find the Print Preview window to close it.
We need to set a spreadsheet font to Courier New in a WPF app using telerik.ui.for.wpf.60.xaml\2024.2.514. As a first step, we do:
using System.Windows;
using Telerik.Documents.Common.Model;
namespace WpfApp4;
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
var fontFamily = new ThemableFontFamily("Courier New");
}
}
Which is fine until we add a required cross-platform project referencing telerik.documents.core\2024.2.426
Then we get:
The type 'ThemableFontFamily' exists in both 'Telerik.Documents.Core, Version=2024.2.426.20, Culture=neutral, PublicKeyToken=5803cfa389c90ce7' and 'Telerik.Windows.Documents.Core, Version=2024.2.426.60, Culture=neutral, PublicKeyToken=5803cfa389c90ce7'
Ambiguous reference.
Candidates are:
Telerik.Documents.Common.Model.ThemableColor
Telerik.Documents.Common.Model.ThemableColor
What is the proper fix for this to reference the version in the WPF app project?