Home » excel » How to download an Excel file that has been opened by Google Sheets?

How to download an Excel file that has been opened by Google Sheets?

Posted by: admin May 14, 2020 Leave a comment

Questions:

I’ve been running into issues when downloading Excel .xlsx files using Google Drive Api v3. The code I’m using is as follows (I’m using the .NET SDK):

using Google.Apis.Auth.OAuth2;
using Google.Apis.Drive.v3;
using Google.Apis.Services;
using Google.Apis.Util.Store;
using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;

namespace DriveQuickstart
{
    class Program
    {
        // If modifying these scopes, delete your previously saved credentials
        // at ~/.credentials/drive-dotnet-quickstart.json
        static string[] Scopes = { DriveService.Scope.Drive };
        static string ApplicationName = "Drive API .NET Quickstart";

        const string FileId = "my_file_id"; //put the ID of the Excel file you want to download here

        public static void Main(string[] args)
        {
            Run().GetAwaiter().GetResult();

            Console.Read();

        }

        private static async Task Run()
        {
            UserCredential credential;

            using (var stream =
                new FileStream("credentials.json", FileMode.Open, FileAccess.Read))
            {
                // The file token.json stores the user's access and refresh tokens, and is created
                // automatically when the authorization flow completes for the first time.
                string credPath = "token.json";
                credential = GoogleWebAuthorizationBroker.AuthorizeAsync(
                    GoogleClientSecrets.Load(stream).Secrets,
                    Scopes,
                    "user",
                    CancellationToken.None,
                    new FileDataStore(credPath, true)).Result;
                Console.WriteLine("Credential file saved to: " + credPath);
            }

            // Create Drive API service.
            var service = new DriveService(new BaseClientService.Initializer()
            {
                HttpClientInitializer = credential,
                ApplicationName = ApplicationName,
            });

            // Define parameters of request.
            FilesResource.GetRequest getRequest = service.Files.Get(FileId);

            using (var stream = new System.IO.FileStream("anExcelFile.xlsx", System.IO.FileMode.OpenOrCreate, System.IO.FileAccess.ReadWrite))
            {
                var downloadProgress = await getRequest.DownloadAsync(stream, CancellationToken.None);
                if (downloadProgress.Exception != null)
                {
                    Console.WriteLine(string.Format("We got error {0} {1} {2}", downloadProgress.Exception.Message, Environment.NewLine, downloadProgress.Exception.StackTrace));
                }
                else
                {
                    Console.WriteLine("Download ok");
                }
            }
        }
    }
}

You can run this sample easily by following the steps described here. This works fine, however, as soon as someone opens the file with Google Sheets and modifies it, I start seeing the following error

D2020-03-16 02:10:13.647293 Response[00000007] Response status: InternalServerError 'Internal Server Error'
D2020-03-16 02:10:13.653278 Response[00000007] An abnormal response wasn't handled. Status code is InternalServerError
D2020-03-16 02:10:13.660288 Response[00000007] Abnormal response is being returned. Status Code is InternalServerError
E2020-03-16 02:10:13.667240 Exception occurred while downloading media The service drive has thrown an exception: Google.GoogleApiException: Internal Server Error
   at Google.Apis.Download.MediaDownloader.<DownloadCoreAsync>d__31.MoveNext()

Looking at the file info after it was open with Google sheets, I can see that its size is changed to 0, so I tried to export it as you would for a Google spreadsheet, like so:

FilesResource.ExportRequest exportRequest = client.Files.Export(fileId, mimeType);

using (var stream = new System.IO.FileStream(fileName, System.IO.FileMode.OpenOrCreate, System.IO.FileAccess.ReadWrite))
{
    await exportRequest.DownloadAsync(stream, cancellationToken);
}

With mimeType = “application/vnd.openxmlformats-officedocument.spreadsheetml.sheet”

However, I then run in the following error:

D2020-03-16 01:53:13.512928 Response[00000003] Response status: Forbidden 'Forbidden'
D2020-03-16 01:53:13.520906 Response[00000003] An abnormal response wasn't handled. Status code is Forbidden
D2020-03-16 01:53:13.525911 Response[00000003] Abnormal response is being returned. Status Code is Forbidden
E2020-03-16 01:53:13.538857 Exception occurred while downloading media The service drive has thrown an exception: Google.GoogleApiException: Google.Apis.Requests.RequestError
Export only supports Google Docs. [403]
Errors [
    Message[Export only supports Google Docs.] Location[ - ] Reason[fileNotExportable] Domain[global]
]

   at Google.Apis.Download.MediaDownloader.<DownloadCoreAsync>d__31.MoveNext()

So it seems that neither downloading nor exporting is working in this particular case. Anything else I should be trying ? Using the webContentLink (https://drive.google.com/uc?id=fileId&export=download) works fine (in a browser that is) so I guess it should be possible to download the file.

How to&Answers:

I raised the issue to Google and it seems it was fixed (cf this issue). I tried again today and following the steps described in the original question, I now can see that after the Excel file has been edited with Google sheets, its size is now greater than 0 and it can be downloaded.

Files that couldn’t be downloaded because of this issue still appear to have the same problem but deleting/reuploading manually these files should make them downloadable.