-
Notifications
You must be signed in to change notification settings - Fork 352
/
Copy pathIndex.razor
122 lines (104 loc) · 4.95 KB
/
Index.razor
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
@page "/"
@implements IDisposable
@using PasteFromExcel.Data
@using System.Collections.ObjectModel
@inject WeatherForecastService ForecastService
@inject IJSRuntime _js
<h6>Sample data copied from Excel (note that Tab used as whitespace) - copy this to paste on top of the grid. You can also find a sample Excel document at the root of the project to copy from</h6>
<pre>
b85a0564-94f3-499e-8b55-42d0af02b8d0 01-Dec-20 14:02:12 123 First
62b38c8f-bde9-4f0e-a3d3-1eb181b80732 02-Dec-20 321 Second
acf34490-c4af-42c5-a21f-bb842769bc1d 03-Dec-20 4:02:12 42 Third
</pre>
@*TabIndex so the div is focusable*@
<div tabindex="1" style="outline:none;" @ref="@pasteContainer">
<TelerikGrid Data="@Forecasts" AutoGenerateColumns="true"
Sortable="true" Pageable="true"
FilterMode="@GridFilterMode.FilterMenu">
</TelerikGrid>
</div>
@code{
ObservableCollection<WeatherForecast> Forecasts { get; set; } // so we can easily add the pasted item if any
ElementReference pasteContainer { get; set; } // to know which element to work with
DotNetObjectReference<Index> CurrComponent { get; set; } // so we can invoke a C# method back here
protected override async Task OnInitializedAsync()
{
var forecasts = await ForecastService.GetForecastAsync(DateTime.Now);
Forecasts = new ObservableCollection<WeatherForecast>(forecasts);
}
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
CurrComponent = DotNetObjectReference.Create<Index>(this);
await _js.InvokeVoidAsync("initializeExcelPasting", pasteContainer, CurrComponent);
}
}
[JSInvokable]
public async Task PasteHandler(string pastedContent)
{
List<WeatherForecast> pastedForecasts = GetPastedForecasts(pastedContent);
foreach (var item in pastedForecasts)
{
// we use an observable collection to update the grid data
// read more here https://docs.telerik.com/blazor-ui/common-features/observable-data
// in a real app, save the data through the service and read it from it
// here we just update the view-model to showcase the concept
Forecasts.Insert(0, item);
}
}
List<WeatherForecast> GetPastedForecasts(string pastedContent)
{
List<WeatherForecast> pastedForecasts = new List<WeatherForecast>();
// Excel MAY add the column names as a first row, so we will remove that, then split by \t characters
// So you may want to remove the first line here to simplify the parsing process. Modify as required
string firstColumnFromFirstRow = pastedContent.Substring(0, pastedContent.IndexOf("\t"));
// Note: there is no really automatic way to tell whether column headers are included - they look just like data
// if the first row is data, our first cell will be the GUID with the ID, so if we can parse that
// then the user copied only data cells. This is a sample heuristic logic for this, implement as necessary
try
{
Guid firstRowGuid = Guid.Parse(firstColumnFromFirstRow);
}
catch
{
// we could not parse the first item to a guid, so we assume it is column headers
// and so we will remove the first row from the data
pastedContent = pastedContent.Substring(pastedContent.IndexOf("\n") + 1);
}
// extract the model or models from the pasted content
// this example is extremely basic, consider finding a NuGet package to
// do this in a safer and more streamlined fashion or otherwise improving this
string[] lines = pastedContent.Split("\n");
foreach (string line in lines)
{
if (string.IsNullOrWhiteSpace(line))
{
continue;//guard against empty lines that Excel may provide
}
string[] splitLine = line.Split('\t');
try
{
WeatherForecast parsedForecast = new WeatherForecast()
{
Id = Guid.Parse(splitLine[0]),
Date = DateTime.Parse(splitLine[1]),
TemperatureC = Convert.ToInt32(splitLine[2]),
// note how the TemperatureF field is missing here - in the default project it has no setter
// so we can't populate it - you may want to add logic to skip it or add a setter
// This is just one example of the many intricacies of such a feature that are
// highly specific for each project, requirements, model and UX
Summary = splitLine[3]
};
pastedForecasts.Add(parsedForecast);
}
catch { }
}
pastedForecasts.Reverse();
return pastedForecasts;
}
public void Dispose()
{
_js.InvokeVoidAsync("cleanUpExcelPasting", pasteContainer);
}
}