Skip to content

Commit 6082d48

Browse files
Add append object method so values can be imported correctly instead of all data importing as strings (#46)
* add append object method so values can be imported correctly instead of just all being strings * Adding method documentation for the new method created --------- Co-authored-by: SteveWinward <[email protected]>
1 parent d3a0928 commit 6082d48

File tree

1 file changed

+119
-0
lines changed

1 file changed

+119
-0
lines changed

src/GoogleSheetsWrapper/SheetAppender.cs

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using System;
12
using System.Collections.Generic;
23
using System.Globalization;
34
using System.IO;
@@ -157,6 +158,76 @@ public void AppendCsv(Stream stream, CsvConfiguration csvConfig, int batchWaitTi
157158
}
158159
}
159160

161+
/// <summary>
162+
/// This lets you append a list of objects to the Google Sheet with any object using reflection to determine the property types during runtime.
163+
/// </summary>
164+
/// <typeparam name="T"></typeparam>
165+
/// <param name="dataRecords">The list of records</param>
166+
/// <param name="batchWaitTime">See https://developers.google.com/sheets/api/limits at last check is 60 requests a minute, so 1 second delay per request should avoid limiting</param>
167+
/// <param name="batchSize">Increasing batch size may improve throughput. Default is conservative.</param>
168+
/// <param name="skipWritingHeaderRow">This boolean indicates if you want to actually write the header row to the Google sheet</param>
169+
public void AppendObject<T>(IEnumerable<T> dataRecords, int batchWaitTime = 1000, int batchSize = 100, bool skipWritingHeaderRow = false) where T : class
170+
{
171+
var batchRowLimit = batchSize;
172+
173+
var rowData = new List<RowData>();
174+
175+
var currentBatchCount = 0;
176+
177+
var properties = typeof(T).GetProperties().Where(x => !x.CustomAttributes.Any(a => a.AttributeType == typeof(CsvHelper.Configuration.Attributes.IgnoreAttribute)));
178+
179+
// Only write the header record if its specified to not skip writing the header row
180+
if (!skipWritingHeaderRow)
181+
{
182+
currentBatchCount++;
183+
184+
var row = new RowData()
185+
{
186+
Values = new List<CellData>()
187+
};
188+
189+
foreach (var header in properties)
190+
{
191+
row.Values.Add(StringToCellData(header.Name));
192+
}
193+
194+
rowData.Add(row);
195+
}
196+
197+
foreach (var record in dataRecords)
198+
{
199+
currentBatchCount++;
200+
201+
var row = new RowData()
202+
{
203+
Values = new List<CellData>()
204+
};
205+
206+
foreach (var property in properties)
207+
{
208+
var propertyValue = property.GetValue(record);
209+
row.Values.Add(ObjectToCellData(propertyValue));
210+
}
211+
212+
rowData.Add(row);
213+
214+
if (currentBatchCount >= batchRowLimit)
215+
{
216+
AppendRows(rowData);
217+
218+
rowData = new List<RowData>();
219+
currentBatchCount = 0;
220+
221+
Thread.Sleep(batchWaitTime);
222+
}
223+
}
224+
225+
if (rowData.Count > 0)
226+
{
227+
AppendRows(rowData);
228+
}
229+
}
230+
160231
/// <summary>
161232
/// Append a single row to the spreadsheet
162233
/// </summary>
@@ -254,5 +325,53 @@ private static CellData StringToCellData(object value)
254325

255326
return cell;
256327
}
328+
329+
/// <summary>
330+
/// Converts a object into its appropriate cell data object
331+
/// </summary>
332+
/// <param name="value"></param>
333+
/// <returns></returns>
334+
private static CellData ObjectToCellData(object value)
335+
{
336+
var cell = new CellData
337+
{
338+
UserEnteredValue = new ExtendedValue()
339+
};
340+
341+
if (value != null)
342+
{
343+
if (value is bool b)
344+
{
345+
cell.UserEnteredValue.BoolValue = b;
346+
}
347+
else if (value is int i)
348+
{
349+
cell.UserEnteredValue.NumberValue = i;
350+
}
351+
else if (value is double dbl)
352+
{
353+
cell.UserEnteredValue.NumberValue = dbl;
354+
}
355+
else if (value is decimal dec)
356+
{
357+
cell.UserEnteredValue.NumberValue = decimal.ToDouble(dec);
358+
}
359+
else if (value is DateTime dt)
360+
{
361+
cell.UserEnteredFormat = new CellFormat { NumberFormat = new NumberFormat { Type = "Date" } };
362+
cell.UserEnteredValue.NumberValue = dt.ToOADate();
363+
}
364+
else
365+
{
366+
cell.UserEnteredValue.StringValue = value.ToString();
367+
}
368+
}
369+
else
370+
{
371+
cell.UserEnteredValue.StringValue = string.Empty;
372+
}
373+
374+
return cell;
375+
}
257376
}
258377
}

0 commit comments

Comments
 (0)