1

I have a problem for which I have been unable to find a solution. I am utilizing the following technologies...

  • C# .NET Durable Function - Timer Trigger
  • Azure Blob Storage - to back up workbook
  • SendGrid - to email workbook
  • ClosedXML (including Report)

I have been unable to generate an excel file, with the 'XLSX' extension, that will open without the following error "Excel cannot open file 'test.xlsx' because the file format or extension is not valid. Verify that the file has not been corrupted and that the file extension matches the format of the file."

Interestingly, I have been able to generate excel files with the 'XLS' extension, that open successfully when downloaded from container storage and email. Unfortunately, that will not suffice as these excel files will be sent to customers.

I am using the following method to update variables within a template stored in Azure. I believe this works, as again, I can generate a 'XLS' file with the referenced cell contents...

{{Value1}}



public async Task<MemoryStream> UpdateVariables(MemoryStream streamTemplate, List<DealDocumentFlattenedForCsv> data)
        {
            var template = new XLTemplate(streamTemplate);
            template.AddVariable("Value1", data[0].Value1);
            template.AddVariable("Value2", data[0].Value2);
            template.AddVariable("Value3", data[0].Value3);
            template.AddVariable("Value4", data[0].Value4);
            template.Generate();
            
            MemoryStream xlsStream = new();
            template.SaveAs(xlsStream);
            await xlsStream.FlushAsync();
            xlsStream.Position = 0;
            return xlsStream;

        }

And successfully populated a table in the Excel template as follows

public async Task<MemoryStream> GetMemoryStreamForExcelDocument(List<DealDocumentFlattenedForCsv> data, MemoryStream stream, string sheetName, string tableName)
        {
            using var workBook = new XLWorkbook(stream);
            
            var table = workBook.Table(tableName);
            table.ReplaceData(data, propagateExtraColumns: true);

            workBook.SaveAs(stream);

            await stream.FlushAsync();

            stream.Position = 0;

            return stream;
        }

I have tried setting content on the email attachment using the following values

  1. application-vnd.ms-excel (prior to 2007 - 'XLS')
  2. application/vnd.openxmlformats-officedocument.spreadsheetml.sheet (2007+ 'XLSX')

And I have tried emailMessage.Attachments / email.AddAttachment, as follows:

private static void BuildEmailMessage(SendGridMessage emailMessage, byte[] csvByteArray)
        {
            emailMessage.AddTo(new EmailAddress("email@email.com"));
            emailMessage.AddContent("text/html", "This is the attachment <b>email</b>");

            emailMessage.Attachments = new List<Attachment>
            {
                new Attachment()
                {
                    Content = Convert.ToBase64String(csvByteArray),
                    Filename = "test.xlsx",
                    Type = "application/vnd.ms-excel",
                    //Type = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
                    Disposition = "attachment"
                }
            };
            //emailMessage.AddAttachment("test.xlsx", Convert.ToBase64String(csvByteArray));
            emailMessage.From = new EmailAddress("email@email.com");
            emailMessage.SetSubject("test msg");
        }

The following are the BlobStorage read and write methods

public MemoryStream ReadFileFromBlobStorage(string fileName, string containerName)
        {
            var blobContainerClient = _blobServiceClient.GetBlobContainerClient(containerName);
            var blob = blobContainerClient.GetBlobClient(fileName);

            var memoryStream = new MemoryStream();
            
            blob.DownloadTo(memoryStream);

            return memoryStream;
        }

        public async Task SaveFileToBlobStorageAsync(string containerName, string fileName, Stream stream)
        {
            stream.Position = 0;
            var containerClient = _blobServiceClient.GetBlobContainerClient(containerName);
            
            var blobClient = containerClient.GetBlobClient(fileName);

            var blobHttpHeaders = new BlobHttpHeaders()
            {
                ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
            };
           
            await blobClient.UploadAsync(stream, blobHttpHeaders, conditions: null);
            stream.Close();
        }

When I download the excel document, with an 'XLSX' extension, I get the following...

Error

Any help would be appreciated. Thank you in advance!

IndyDev
  • 81
  • 1
  • 10
  • Can you open the file in Excel before you email it with SendGrid? – philnash Jul 26 '22 at 05:37
  • Good morning @philnash! ClosedXML pulls a template from blob storage, updates cells and a table. Then the code saves that change to a blob container and sends it via SendGrid to a customer. I have successfully created 'XLS' files via this process. I am trying to create an uncorrupted 'XLSX' file. I tried all day yesterday. Decided to post this question hoping someone with more experience might see my mistake. Thank you for asking! – IndyDev Jul 26 '22 at 11:10
  • Ok, so I’m trying to isolate where the issue is. Can you create a successful XLSX file by running the code locally on your own machine? – philnash Jul 26 '22 at 11:13
  • I have not tried to create it locally as yet. Unfortunately, I won't be able to do so for a while as I have several meetings today. I will post here again with the result of that exercise asap. I will ensure you see it @philnash. I appreciate your interest / help very much! – IndyDev Jul 26 '22 at 11:42
  • @philnash....Sorry so long to get back. A lot going on last week. This morning I tried saving the stream locally. The same result. 'XLSX' file is corrupted. SendGrid and BlobStorage are no longer in play. – IndyDev Aug 01 '22 at 11:27
  • I'm sorry, I'm not actually a C# developer. I was trying to work out whether the issue lay in SendGrid or your blob storage (I had a much better chance at fixing it if it was SendGrid!). Hopefully this has helped isolate the issue, maybe it's something you could raise against the [ClosedXML project](https://github.com/ClosedXML/ClosedXML/issues) if the code looks right. – philnash Aug 01 '22 at 11:39

0 Answers0