Create And Update Google SpreadSheet Via Google API.NET Library

Background

 
Recently, I was working on a proof of concept to SharePoint to GSuite data/content migration. As part of this POC, I was required to use Google API to create a spreadsheet and add data to the spreadsheet using .NET. The source data was to be read from SharePoint List items using CSOM. 
 
The Generic Idea here is to create a new spreadsheet using Drive API and then use the Sheet API to update data in the spreadsheet.
 
If you don't have the basic understanding of Drive and Sheet API,  I would request you to go through the below links.
  • https://developers.google.com/drive/api/
  • https://developers.google.com/sheets/api/
Prerequisites 
  • Enable Google Drive and Spreadsheet API to generate the client Id and client secret (crendentials.json) which will be used later. There are many articles already available on how to do this. So, I won't explain it here. Please refer to the below links for quick reference.

    https://developers.google.com/drive/api/v3/quickstart/dotnet
    https://developers.google.com/sheets/api/quickstart/dotnet  


    Please note that if you are doing this in ASP.NET, you have to generate the client id and secret for the web application.  
  • Create a Windows Console application or web application (using Visual Studio)
  • Add a reference to Google API dll via NuGet package. Alternatively, you can download it manually from nuget.org link and add references.
  • Below is a screenshot of DLLs required.
Create And Update Google SpreadSheet Via Google API.NET Library
 
Now, let us start with code snippets.
  

Create a Spreadsheet 

 
Call the below method to create a spreadsheet. I have added comments to explain.
  1. public Google.Apis.Drive.v3.Data.File CreateSheet()  
  2. {  
  3.       string[] scopes = new string[] { DriveService.Scope.Drive,  
  4.                       DriveService.Scope.DriveFile,};  
  5.      var clientId = "123456337-wajklowlksflmxiowerasjdflsl.apps.googleusercontent.com";      // From https://console.developers.google.com  
  6.      var clientSecret = "kkslfdkiwowol_ssdwerss";          // From https://console.developers.google.com  
  7.      // here is where we Request the user to give us access, or use the Refresh Token that was previously stored in %AppData%  
  8.      var credential = GoogleWebAuthorizationBroker.AuthorizeAsync(new ClientSecrets  
  9.      {  
  10.          ClientId = clientId,  
  11.          ClientSecret = clientSecret  
  12.      },scopes,  
  13.      Environment.UserName,CancellationToken.None,new FileDataStore("MyAppsToken")).Result;  
  14.      //Once consent is recieved, your token will be stored locally on the AppData directory, so that next time you wont be prompted for consent.   
  15.      DriveService _service = new DriveService(new BaseClientService.Initializer()  
  16.      {  
  17.          HttpClientInitializer = credential,  
  18.          ApplicationName = "MyAppName",  
  19.   
  20.      });  
  21.     var _parent = "";//ID of folder if you want to create spreadsheet in specific folder
  22.     var filename = "helloworld";
  23.     var fileMetadata = new Google.Apis.Drive.v3.Data.File()  
  24.     {  
  25.         Name = filename,  
  26.         MimeType = "application/vnd.google-apps.spreadsheet",  
  27.         //TeamDriveId = teamDriveID, // IF you want to add to specific team drive  
  28.     };  
  29.     FilesResource.CreateRequest request = _service.Files.Create(fileMetadata);  
  30.     request.SupportsTeamDrives = true;  
  31.     fileMetadata.Parents = new List<string> { _parent }; // Parent folder id or TeamDriveID  
  32.     request.Fields = "id";  
  33.     System.Net.ServicePointManager.ServerCertificateValidationCallback = delegate (object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) { return true; };  
  34.     var file = request.Execute();  
  35.     MessageBox.Show("File ID: " + file.Id);  
  36.     return file;  
  37. }  
Now, let us see what will happen when the above method is executed, assuming we are calling this method on button click of a Windows application like the  below 'Create Spreadsheet'.
 
Create And Update Google SpreadSheet Via Google API.NET Library
 
A new browser window would open asking to authenticate the user. Enter your Google credentials.
 
Create And Update Google SpreadSheet Via Google API.NET Library
 
The User Consent screen will be displayed. Provide access to the Google Drive.
 
Create And Update Google SpreadSheet Via Google API.NET Library
 
A success message will be displayed with the file's id.
 
Create And Update Google SpreadSheet Via Google API.NET Library
 
Go to Google drive; a file with name 'helloworld' will be created of type spreadsheet.
 
Create And Update Google SpreadSheet Via Google API.NET Library
 

Update SpreadSheet

 
Call the below method to add data to the spreadsheet created above. To reuse some code, I have segregated the logic into different methods. All the supporting methods are also added here for reference. 
  1. private UpdateSpreadSheet()  
  2.       {  
  3.          // SpreadhSheetID of above created document.  
  4.           var SheetId = "1ZCIKtF2FE2BHnIgmiLu3junMJGKRDJfU2RbXQ_BksN8";   
  5.           var service = AuthorizeGoogleAppForSheetsService();  
  6.           string newRange = GetRange(service,SheetId);  
  7.           IList<IList<Object>> objNeRecords = GenerateData();  
  8.           UpdatGoogleSheetinBatch(objNeRecords, SheetId, newRange, service);  
  9.           MessageBox.Show("done!");  
  10.       }  
Method to start authorization flow
 
Note
Here, we are using the spreadsheetcredentials.json file to pass client id and client secret. This is another way to pass client id and secret rather than hardcoding in code. This JSON file can be downloaded from console.developers.google.com. 
  1. private static SheetsService AuthorizeGoogleAppForSheetsService()  
  2.        {  
  3.            // If modifying these scopes, delete your previously saved credentials  
  4.            // at ~/.credentials/sheets.googleapis.com-dotnet-quickstart.json  
  5.            string[] Scopes = { SheetsService.Scope.Spreadsheets };  
  6.            string ApplicationName = "Google Sheets API .NET Quickstart";  
  7.            UserCredential credential;  
  8.            using (var stream =  
  9.               new FileStream("spreadsheetcredentials.json", FileMode.Open, FileAccess.Read))  
  10.            {  
  11.                  
  12.                credential = GoogleWebAuthorizationBroker.AuthorizeAsync(  
  13.                    GoogleClientSecrets.Load(stream).Secrets,  
  14.                    Scopes,  
  15.                    "user",  
  16.                    CancellationToken.None,  
  17.                    new FileDataStore("MyAppsToken")).Result;  
  18.                  
  19.            }  
  20.   
  21.            // Create Google Sheets API service.  
  22.            var service = new SheetsService(new BaseClientService.Initializer()  
  23.            {  
  24.                HttpClientInitializer = credential,  
  25.                ApplicationName = ApplicationName,  
  26.            });  
  27.   
  28.            return service;  
  29.        }  
Method to get the range of row and column from where we need to add data to the spreadsheet -- if there are no previous values added, start from the first row and column.
  1. protected static string GetRange(SheetsService service,string SheetId)  
  2.        {  
  3.            // Define request parameters.  
  4.            String spreadsheetId = SheetId;  
  5.            String range = "A:A";  
  6.   
  7.            SpreadsheetsResource.ValuesResource.GetRequest getRequest =  
  8.                       service.Spreadsheets.Values.Get(spreadsheetId, range);  
  9.            System.Net.ServicePointManager.ServerCertificateValidationCallback = delegate (object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) { return true; };  
  10.            ValueRange getResponse = getRequest.Execute();  
  11.            IList<IList<Object>> getValues = getResponse.Values;  
  12.            if(getValues == null)  
  13.            {  
  14.                // spreadsheet is empty return Row A Column A  
  15.                return "A:A";  
  16.            }  
  17.              
  18.            int currentCount = getValues.Count() + 1;  
  19.            String newRange = "A" + currentCount + ":A";  
  20.            return newRange;  
  21.        }  
Method to generate data in required format - Here, we will add 5 rows with 3 columns. 
  1. private static IList<IList<Object>> GenerateData()  
  2. {  
  3.     List<IList<Object>> objNewRecords = new List<IList<Object>>();  
  4.     int maxrows = 5;  
  5.     for (var i = 1;i<=maxrows;i++ )  
  6.     {  
  7.         IList<Object> obj = new List<Object>();  
  8.         obj.Add("Data row value - " + i + "A");  
  9.         obj.Add("Data row value - " + i + "B");  
  10.         obj.Add("Data row value - " + i + "C");  
  11.         objNewRecords.Add(obj);  
  12.     }  
  13.     return objNewRecords;  
  14. }  
Call a method to make a request to Google Spreadsheet API and pass all the required objects. 
  1. private static void UpdatGoogleSheetinBatch(IList<IList<Object>> values, string spreadsheetId, string newRange, SheetsService service)  
  2.        {  
  3.            SpreadsheetsResource.ValuesResource.AppendRequest request =  
  4.               service.Spreadsheets.Values.Append(new ValueRange() { Values = values }, spreadsheetId, newRange);  
  5.            request.InsertDataOption = SpreadsheetsResource.ValuesResource.AppendRequest.InsertDataOptionEnum.INSERTROWS;  
  6.            request.ValueInputOption = SpreadsheetsResource.ValuesResource.AppendRequest.ValueInputOptionEnum.RAW;  
  7.            var response = request.Execute();  
  8.        }  

We have all our methods ready. Now, let us see what will happen when the above UpdateSpreadSheet is executed, assuming we are calling this method on button click of a Windows application 'Update Spreadsheet'. If the user is not authenticated, we will go through the similar process where a browser window will ask to authenticate user. 

Once the process is completed, we will get a Message box with 'done!'. Let us go to Google Drive and open the same helloworld file to see the changes.
  
Create And Update Google SpreadSheet Via Google API.NET Library
  
Hope this helps...Happy coding.!!!!