From e6fa5d69e9d70614ab960d8956eb2623cd313623 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 2 Sep 2026 13:52:11 +0000 Subject: [PATCH 1/5] Document sheet helper APIs Co-authored-by: SteveWinward <2002602+SteveWinward@users.noreply.github.com> --- src/GoogleSheetsWrapper/SheetExporter.cs | 30 +++---- .../SheetFieldAttributeUtils.cs | 40 +++++----- src/GoogleSheetsWrapper/SheetHelper.cs | 80 +++++++++---------- src/GoogleSheetsWrapper/SheetRange.cs | 46 +++++------ .../Utils/PhoneNumberParsing.cs | 18 ++--- 5 files changed, 107 insertions(+), 107 deletions(-) diff --git a/src/GoogleSheetsWrapper/SheetExporter.cs b/src/GoogleSheetsWrapper/SheetExporter.cs index 17d2598..4fca382 100644 --- a/src/GoogleSheetsWrapper/SheetExporter.cs +++ b/src/GoogleSheetsWrapper/SheetExporter.cs @@ -18,9 +18,9 @@ public class SheetExporter /// /// Constructor /// - /// - /// - /// + /// The identifier of the spreadsheet to export. + /// The service account email used for authentication. + /// The tab to export. public SheetExporter(string spreadsheetID, string serviceAccountEmail, string tabName) { _sheetHelper = new SheetHelper(spreadsheetID, serviceAccountEmail, tabName); @@ -29,16 +29,16 @@ public SheetExporter(string spreadsheetID, string serviceAccountEmail, string ta /// /// Constructor /// - /// + /// The initialized sheet helper to use for export operations. public SheetExporter(SheetHelper sheetHelper) { _sheetHelper = sheetHelper; } /// - /// + /// Initializes the underlying sheet helper using service account credentials. /// - /// + /// Service account credentials in JSON format. public void Init(string jsonCredentials) { _sheetHelper.Init(jsonCredentials); @@ -47,9 +47,9 @@ public void Init(string jsonCredentials) /// /// Exports the current Google Sheet tab to a CSV file /// - /// - /// - /// + /// The range to export. + /// The destination stream for the CSV content. + /// The delimiter used between CSV fields. public void ExportAsCsv(SheetRange range, Stream stream, string delimiter = ",") { var config = new CsvConfiguration(CultureInfo.InvariantCulture) @@ -63,9 +63,9 @@ public void ExportAsCsv(SheetRange range, Stream stream, string delimiter = ",") /// /// Exports the current Google Sheet tab to a CSV file. This override lets you explicitly specify the CsvConfiguration object for the CsvHelper library. /// - /// - /// - /// + /// The range to export. + /// The destination stream for the CSV content. + /// The CsvHelper settings used to generate the CSV content. public void ExportAsCsv(SheetRange range, Stream stream, CsvConfiguration csvConfiguration) { var rows = _sheetHelper.GetRowsFormatted(range); @@ -84,10 +84,10 @@ public void ExportAsCsv(SheetRange range, Stream stream, CsvConfiguration csvCon } /// - /// Exports the current Google Sheet tab to a CSV file + /// Exports the specified Google Sheet range to an Excel workbook. /// - /// - /// + /// The range to export. + /// The destination stream for the Excel workbook. public void ExportAsExcel(SheetRange range, Stream stream) { var rows = _sheetHelper.GetRowsFormatted(range); diff --git a/src/GoogleSheetsWrapper/SheetFieldAttributeUtils.cs b/src/GoogleSheetsWrapper/SheetFieldAttributeUtils.cs index e0008d9..533d303 100644 --- a/src/GoogleSheetsWrapper/SheetFieldAttributeUtils.cs +++ b/src/GoogleSheetsWrapper/SheetFieldAttributeUtils.cs @@ -14,12 +14,12 @@ namespace GoogleSheetsWrapper public class SheetFieldAttributeUtils { /// - /// + /// Populates the attributed properties of a record from a row returned by Google Sheets. /// - /// - /// - /// - /// + /// The record type to populate. + /// The record instance to populate. + /// The source row values. + /// The one-based column index represented by the first value in . /// public static void PopulateRecord(T record, IList row, int minColumnId = 1) where T : BaseRecord { @@ -99,11 +99,11 @@ public static void PopulateRecord(T record, IList row, int minColumnI /// /// Converts the objects values to CellData object for Google Sheets API /// - /// - /// - /// - /// - /// + /// The record type containing the property. + /// The record that provides the property value. + /// The sheet metadata that defines the cell format. + /// The property to convert. + /// A Google Sheets cell containing the property's value and formatting. /// public static CellData GetCellDataForSheetField(T record, SheetFieldAttribute attribute, PropertyInfo property) { @@ -238,11 +238,11 @@ public static CellData GetCellDataForSheetField(T record, SheetFieldAttribute } /// - /// + /// Gets the one-based sheet column index associated with a record property. /// - /// - /// - /// + /// The record type that declares the property. + /// An expression that selects the attributed property. + /// The property's configured column index. public static int GetColumnId(Expression> expression) where T : BaseRecord { var attribute = GetSheetFieldAttribute(expression); @@ -251,20 +251,20 @@ public static int GetColumnId(Expression> expression) where T } /// - /// + /// Gets all sheet field metadata declared by a record type, ordered by column index. /// - /// - /// + /// The record type to inspect. + /// The sheet field attributes and their associated properties. public static SortedDictionary GetAllSheetFieldAttributes() { return GetAllSheetFieldAttributes(typeof(T)); } /// - /// + /// Gets all sheet field metadata declared by a type, ordered by column index. /// - /// - /// + /// The type to inspect. + /// The sheet field attributes and their associated properties. public static SortedDictionary GetAllSheetFieldAttributes(Type type) { var result = new SortedDictionary(new SheetFieldAttributeComparer()); diff --git a/src/GoogleSheetsWrapper/SheetHelper.cs b/src/GoogleSheetsWrapper/SheetHelper.cs index 4df669d..0560c1f 100644 --- a/src/GoogleSheetsWrapper/SheetHelper.cs +++ b/src/GoogleSheetsWrapper/SheetHelper.cs @@ -38,7 +38,7 @@ public class SheetHelper public string ServiceAccountEmail { get; set; } /// - /// + /// OAuth scopes requested when authenticating with the Google Sheets API. /// public string[] Scopes { get; set; } = { SheetsService.Scope.Spreadsheets }; @@ -55,9 +55,9 @@ public class SheetHelper /// /// Constructor /// - /// - /// - /// + /// The identifier of the spreadsheet to access. + /// The service account email used to impersonate an account. + /// The tab to select after initialization. public SheetHelper(string spreadsheetID, string serviceAccountEmail, string tabName) { SpreadsheetID = spreadsheetID; @@ -68,7 +68,7 @@ public SheetHelper(string spreadsheetID, string serviceAccountEmail, string tabN /// /// Initializes the SheetHelper object /// - /// + /// Service account credentials in JSON format. public void Init(string jsonCredentials) { Init(jsonCredentials, default); @@ -77,8 +77,8 @@ public void Init(string jsonCredentials) /// /// Initializes the SheetHelper object with authentication /// - /// - /// + /// Service account credentials in JSON format. + /// Factory used to create HTTP clients for API requests. public void Init(string jsonCredentials, Google.Apis.Http.IHttpClientFactory httpClientFactory) { var credential = (ServiceAccountCredential) @@ -121,7 +121,7 @@ protected void EnsureServiceInitialized() /// /// Set the tab to the specified newTabName value /// - /// + /// The existing tab to select, or the name of a tab to create. public void UpdateTabName(string newTabName) { EnsureServiceInitialized(); @@ -156,7 +156,7 @@ public void UpdateTabName(string newTabName) /// /// Returns a list of all tab names in the Google Spreadsheet /// - /// + /// The titles of all tabs in the spreadsheet. public List GetAllTabNames() { EnsureServiceInitialized(); @@ -173,10 +173,10 @@ public List GetAllTabNames() /// /// Return a collection of rows for a given SheetRange input /// - /// - /// - /// - /// + /// The range to retrieve. + /// How cell values are returned by the API. + /// How date and time values are returned by the API. + /// The values in the requested rows, or an empty collection when no values exist. public IList> GetRows(SheetRange range, ValueRenderOptionEnum valueRenderOption = ValueRenderOptionEnum.UNFORMATTEDVALUE, DateTimeRenderOptionEnum dateTimeRenderOption = DateTimeRenderOptionEnum.SERIALNUMBER) @@ -206,8 +206,8 @@ public IList> GetRows(SheetRange range, /// /// Return a collection of rows formatted values for a given SheetRange input /// - /// - /// + /// The range to retrieve. + /// The formatted values in the requested rows, or an empty collection when no values exist. public IList> GetRowsFormatted(SheetRange range) { EnsureServiceInitialized(); @@ -235,8 +235,8 @@ public IList> GetRowsFormatted(SheetRange range) /// /// Clears values from a spreadsheet (NOTE: All other properties of the cell (such as formatting, data validation, etc..) are kept.) /// - /// - /// + /// The range whose values should be cleared. + /// The API response describing the cleared range. public ClearValuesResponse ClearRange(SheetRange range) { EnsureServiceInitialized(); @@ -252,8 +252,8 @@ public ClearValuesResponse ClearRange(SheetRange range) /// /// Deletes a specified column /// - /// - /// + /// The one-based index of the column to delete. + /// The response from the batch update operation. public BatchUpdateSpreadsheetResponse DeleteColumn(int col) { EnsureServiceInitialized(); @@ -284,8 +284,8 @@ public BatchUpdateSpreadsheetResponse DeleteColumn(int col) /// /// Deletes a specified column /// - /// - /// + /// The letter-based column identifier to delete. + /// The response from the batch update operation. public BatchUpdateSpreadsheetResponse DeleteColumn(string columnLetter) { EnsureServiceInitialized(); @@ -298,8 +298,8 @@ public BatchUpdateSpreadsheetResponse DeleteColumn(string columnLetter) /// /// Deletes a specified row /// - /// - /// + /// The one-based index of the row to delete. + /// The response from the batch update operation. public BatchUpdateSpreadsheetResponse DeleteRow(int row) { EnsureServiceInitialized(); @@ -328,11 +328,11 @@ public BatchUpdateSpreadsheetResponse DeleteRow(int row) } /// - /// + /// Deletes all rows in the inclusive range. /// - /// - /// - /// + /// The one-based index of the first row to delete. + /// The one-based index of the last row to delete. + /// The response from the batch update operation. public BatchUpdateSpreadsheetResponse DeleteRows(int startRow, int endRow) { EnsureServiceInitialized(); @@ -363,8 +363,8 @@ public BatchUpdateSpreadsheetResponse DeleteRows(int startRow, int endRow) /// /// Inserts a blank new column using the column index as the id (NOTE: 1 is the first index for the column based index) /// - /// - /// + /// The one-based index where the column is inserted. + /// The response from the batch update operation. public BatchUpdateSpreadsheetResponse InsertBlankColumn(int column) { EnsureServiceInitialized(); @@ -401,8 +401,8 @@ public BatchUpdateSpreadsheetResponse InsertBlankColumn(int column) /// /// Inserts a blank new column using a letter notation (i.e. B2 as the column id) /// - /// - /// + /// The letter-based column identifier where the column is inserted. + /// The response from the batch update operation. public BatchUpdateSpreadsheetResponse InsertBlankColumn(string columnLetter) { EnsureServiceInitialized(); @@ -415,8 +415,8 @@ public BatchUpdateSpreadsheetResponse InsertBlankColumn(string columnLetter) /// /// Inserts a new blank row /// - /// - /// + /// The one-based index where the row is inserted. + /// The response from the batch update operation. public BatchUpdateSpreadsheetResponse InsertBlankRow(int row) { EnsureServiceInitialized(); @@ -455,12 +455,12 @@ public BatchUpdateSpreadsheetResponse InsertBlankRow(int row) /// /// This is useful to avoid throttling limits with the Google Sheets API /// - /// + /// The cell ranges and data to update. /// Allows you to specify what fields you want to update in the BatchUpdate call, /// defaults to userEnteredValue to keep existing cell styles, use "*" to update all properties here. /// Other valid field mask values are: dataSourceFormula, dataSourceTable, dataValidation, effectiveFormat, effectiveValue, formattedValue, hyperlink, note, pivotTable, textFormatRuns, userEnteredFormat, userEnteredValue /// - /// + /// The response from the batch update operation. public BatchUpdateSpreadsheetResponse BatchUpdate(List updates, string fieldMask = "userEnteredValue") { EnsureServiceInitialized(); @@ -554,15 +554,15 @@ public class SheetHelper : SheetHelper where T : BaseRecord /// /// /// - /// + /// The tab to which records are appended. public SheetHelper(string spreadsheetID, string serviceAccountEmail, string tabName) : base(spreadsheetID, serviceAccountEmail, tabName) { } /// /// Adds a record to the next row in the Google Sheet tab /// - /// - /// + /// The record to append. + /// The response from the batch update operation. public BatchUpdateSpreadsheetResponse AppendRow(T record) { EnsureServiceInitialized(); @@ -573,8 +573,8 @@ public BatchUpdateSpreadsheetResponse AppendRow(T record) /// /// Adds mulitlpe rows to the next row in the Google Sheets tab /// - /// - /// + /// The records to append. + /// The response from the batch update operation. public BatchUpdateSpreadsheetResponse AppendRows(IList records) { EnsureServiceInitialized(); diff --git a/src/GoogleSheetsWrapper/SheetRange.cs b/src/GoogleSheetsWrapper/SheetRange.cs index ba8d540..fdd14ad 100644 --- a/src/GoogleSheetsWrapper/SheetRange.cs +++ b/src/GoogleSheetsWrapper/SheetRange.cs @@ -10,12 +10,12 @@ namespace GoogleSheetsWrapper public class SheetRange : IEquatable { /// - /// Is this A1 notation? + /// Gets the range expressed in A1 notation when the range has an end column. /// public string A1Notation { get; private set; } /// - /// Is this R1C1 notation? + /// Gets the range expressed in R1C1 notation. /// public string R1C1Notation { get; private set; } @@ -95,11 +95,11 @@ private static readonly List aToZ /// /// Row and column numbers are 1 based indexes /// - /// - /// - /// - /// - /// + /// The optional sheet tab name. + /// The one-based index of the first column. + /// The one-based index of the first row. + /// The optional one-based index of the last column. + /// The optional one-based index of the last row. public SheetRange(string tabName, int startColumn, int startRow, int? endColumn = null, int? endRow = null) { _startColumn = startColumn; @@ -114,7 +114,7 @@ public SheetRange(string tabName, int startColumn, int startRow, int? endColumn /// /// Create a SheetRange from an A1 notation or an R1C1 notation /// - /// + /// A valid A1 or R1C1 range expression. public SheetRange(string rangeValue) { SheetRange range; @@ -146,8 +146,8 @@ public SheetRange(string rangeValue) /// /// columnId is a 1 based index /// - /// - /// + /// The one-based column index. + /// The corresponding A1 column letters. public static string GetLettersFromColumnID(int columnID) { var block = columnID - 1; @@ -169,8 +169,8 @@ public static string GetLettersFromColumnID(int columnID) /// /// The resulting column id is on a 1 based index (i.e. A => 1) /// - /// - /// + /// The A1 column letters to convert. + /// The corresponding one-based column index. public static int GetColumnIDFromLetters(string letters) { var result = 0; @@ -245,10 +245,10 @@ private void UpdateFieldAndNotiationProperties(ref T currentValue, T newValue #region IEquatable Interface Implementation /// - /// + /// Calculates a hash code from the range coordinates and tab name. /// - /// - /// + /// The range for which to calculate a hash code. + /// A hash code for the specified range. public static int GetHashCode(SheetRange obj) { return HashCode.Combine( @@ -260,10 +260,10 @@ public static int GetHashCode(SheetRange obj) } /// - /// + /// Determines whether this range has the same coordinates and notation as another range. /// - /// - /// + /// The range to compare with this instance. + /// when the ranges are equal; otherwise, . public bool Equals(SheetRange other) { return @@ -279,19 +279,19 @@ public bool Equals(SheetRange other) } /// - /// + /// Determines whether this range equals another object. /// - /// - /// + /// The object to compare with this instance. + /// when the object is an equal range; otherwise, . public override bool Equals(object obj) { return Equals((SheetRange)obj); } /// - /// + /// Returns a hash code based on the range coordinates and tab name. /// - /// + /// A hash code for this range. public override int GetHashCode() { return GetHashCode(this); diff --git a/src/GoogleSheetsWrapper/Utils/PhoneNumberParsing.cs b/src/GoogleSheetsWrapper/Utils/PhoneNumberParsing.cs index 94a6de2..91fa87b 100644 --- a/src/GoogleSheetsWrapper/Utils/PhoneNumberParsing.cs +++ b/src/GoogleSheetsWrapper/Utils/PhoneNumberParsing.cs @@ -9,30 +9,30 @@ namespace GoogleSheetsWrapper.Utils public class PhoneNumberParsing { /// - /// + /// Removes a leading United States country code and all non-numeric characters. /// - /// - /// + /// The phone number to normalize. + /// The normalized phone number containing digits only. public static string RemoveUSInterationalPhoneCode(string number) { return RemoveExtraCharactersFromPhoneNumber(number.Replace("+1", "")); } /// - /// + /// Removes all non-numeric characters from a phone number. /// - /// - /// + /// The phone number to normalize. + /// The phone number containing digits only. public static string RemoveExtraCharactersFromPhoneNumber(string number) { return Regex.Replace(number, @"[^\d]", ""); } /// - /// + /// Converts a normalized United States phone number to a numeric value. /// - /// - /// + /// The phone number to convert. + /// The numeric phone number without its country code. public static long ConvertToLong(string number) { var numberAsString = RemoveExtraCharactersFromPhoneNumber(number.Replace("+1", "")); From 9729df7642071a6e12cdcffea4f9849c1e2b58ed Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 2 Sep 2026 13:53:37 +0000 Subject: [PATCH 2/5] Fix sheet helper documentation typo Co-authored-by: SteveWinward <2002602+SteveWinward@users.noreply.github.com> --- src/GoogleSheetsWrapper/SheetHelper.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/GoogleSheetsWrapper/SheetHelper.cs b/src/GoogleSheetsWrapper/SheetHelper.cs index 0560c1f..d8f56d1 100644 --- a/src/GoogleSheetsWrapper/SheetHelper.cs +++ b/src/GoogleSheetsWrapper/SheetHelper.cs @@ -571,7 +571,7 @@ public BatchUpdateSpreadsheetResponse AppendRow(T record) } /// - /// Adds mulitlpe rows to the next row in the Google Sheets tab + /// Adds multiple rows to the next row in the Google Sheets tab /// /// The records to append. /// The response from the batch update operation. From 615cb9a6207c8fc4342a6615780b9711dbf8dd07 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 2 Sep 2026 13:57:09 +0000 Subject: [PATCH 3/5] Bump package minor version Co-authored-by: SteveWinward <2002602+SteveWinward@users.noreply.github.com> --- src/GoogleSheetsWrapper/GoogleSheetsWrapper.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/GoogleSheetsWrapper/GoogleSheetsWrapper.csproj b/src/GoogleSheetsWrapper/GoogleSheetsWrapper.csproj index 9b22b33..a1b2ea0 100644 --- a/src/GoogleSheetsWrapper/GoogleSheetsWrapper.csproj +++ b/src/GoogleSheetsWrapper/GoogleSheetsWrapper.csproj @@ -8,7 +8,7 @@ https://github.com/SteveWinward/GoogleSheetsWrapper LICENSE https://github.com/SteveWinward/GoogleSheetsWrapper - 2.0.26 + 2.1.0 Google Sheets README.md A simple wrapper library that makes it easier to perform CRUD operations against Google Sheets spreadsheets. From 80b02313e18c60b11f7cf8bfe70e83f0136c9595 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 2 Sep 2026 14:02:28 +0000 Subject: [PATCH 4/5] Set package version 2.0.27 Co-authored-by: SteveWinward <2002602+SteveWinward@users.noreply.github.com> --- src/GoogleSheetsWrapper/GoogleSheetsWrapper.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/GoogleSheetsWrapper/GoogleSheetsWrapper.csproj b/src/GoogleSheetsWrapper/GoogleSheetsWrapper.csproj index a1b2ea0..43e758f 100644 --- a/src/GoogleSheetsWrapper/GoogleSheetsWrapper.csproj +++ b/src/GoogleSheetsWrapper/GoogleSheetsWrapper.csproj @@ -8,7 +8,7 @@ https://github.com/SteveWinward/GoogleSheetsWrapper LICENSE https://github.com/SteveWinward/GoogleSheetsWrapper - 2.1.0 + 2.0.27 Google Sheets README.md A simple wrapper library that makes it easier to perform CRUD operations against Google Sheets spreadsheets. From b3e0ac39275440480c3b708c44825f5760814027 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 2 Sep 2026 14:22:38 +0000 Subject: [PATCH 5/5] Clarify PhoneNumberParsing XML docs to match implementation Co-authored-by: SteveWinward <2002602+SteveWinward@users.noreply.github.com> --- src/GoogleSheetsWrapper/Utils/PhoneNumberParsing.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/GoogleSheetsWrapper/Utils/PhoneNumberParsing.cs b/src/GoogleSheetsWrapper/Utils/PhoneNumberParsing.cs index 91fa87b..f56c448 100644 --- a/src/GoogleSheetsWrapper/Utils/PhoneNumberParsing.cs +++ b/src/GoogleSheetsWrapper/Utils/PhoneNumberParsing.cs @@ -9,7 +9,7 @@ namespace GoogleSheetsWrapper.Utils public class PhoneNumberParsing { /// - /// Removes a leading United States country code and all non-numeric characters. + /// Removes any occurrence of the United States country code ("+1") and all non-numeric characters. /// /// The phone number to normalize. /// The normalized phone number containing digits only. @@ -32,7 +32,7 @@ public static string RemoveExtraCharactersFromPhoneNumber(string number) /// Converts a normalized United States phone number to a numeric value. /// /// The phone number to convert. - /// The numeric phone number without its country code. + /// The numeric phone number with any occurrence of the United States country code ("+1") removed. public static long ConvertToLong(string number) { var numberAsString = RemoveExtraCharactersFromPhoneNumber(number.Replace("+1", ""));