简体   繁体   English

将OpenXML创建的Excel电子表格导出到客户端

[英]Exporting OpenXML created Excel Spreadsheet to client side

I am trying to get the API to start a download of the excel spreadsheet that has been created. 我正在尝试获取API,以开始下载已创建的excel电子表格。 Although, i seem to be running into some hassle. 虽然,我似乎遇到了一些麻烦。 I have tried to also send the Byte array of the Spreadsheets memory stream through to the front-end and go from there, but the excel file is corrupt and does not contain any data. 我也尝试过将电子表格内存流的字节数组发送到前端,然后从那里去,但是excel文件已损坏,并且不包含任何数据。

Controller: 控制器:

    [HttpPost]
    [Route("CreateExcelDocument")]
    public ActionResult CreateExcelDocument([FromBody] List<BarBillList> model)
    {
        try
        {
            byte[] tmp;
            using (ExcelController ex = new ExcelController())
            {
                tmp = ex.createExcelSpreadsheet(barBillExport);
            }

            string fileName = "xxx.xlsx";
            return File(tmp, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", fileName);
        }
        catch (Exception e)
        {
            return null;
        }
    }

ExcelController class with the spreadsheet creation method: 具有电子表格创建方法的ExcelController类:

 public byte[] createExcelSpreadsheet(List<BarBillList> barBillExport)
    {
        DateTime today = DateTime.Today;
        using (MemoryStream ms = new MemoryStream())
        {
            using (SpreadsheetDocument document = SpreadsheetDocument.Create(ms, SpreadsheetDocumentType.Workbook))
            {
                //Creating the initial document
                WorkbookPart workbookPart = document.AddWorkbookPart();
                workbookPart.Workbook = new Workbook();

                WorksheetPart worksheetPart = workbookPart.AddNewPart<WorksheetPart>();
                worksheetPart.Worksheet = new Worksheet();

                workbookPart.Workbook.Save();

                //Styling the doucment
                WorkbookStylesPart stylesPart = workbookPart.AddNewPart<WorkbookStylesPart>();
                stylesPart.Stylesheet = GenerateStyleSheet();
                stylesPart.Stylesheet.Save();

                //Adding width to the columns
                DocumentFormat.OpenXml.Spreadsheet.Columns columns = new DocumentFormat.OpenXml.Spreadsheet.Columns();
                columns.Append(new DocumentFormat.OpenXml.Spreadsheet.Column() { Min = 1, Max = 6, Width = 20, CustomWidth = true });
                worksheetPart.Worksheet.Append(columns);

                //Creating the worksheet part to add the data to
                Sheets sheets = workbookPart.Workbook.AppendChild(new Sheets());
                Sheet sheet = new Sheet() { Id = workbookPart.GetIdOfPart(worksheetPart), SheetId = 1, Name = "BarBill" };
                sheets.Append(sheet);

                SheetData sheetData = worksheetPart.Worksheet.AppendChild(new SheetData());

                //Creating the first Header Row
                Row row = new Row();
                row.Append(
                    ConstructCell("Name", CellValues.String, true),
                    ConstructCell("Last Payment Date", CellValues.String, true),
                    ConstructCell("Last Payment Amount", CellValues.String, true),
                    ConstructCell("Current Balance", CellValues.String, true));

                sheetData.AppendChild(row);

                //Appending the data into their respective columns 
                foreach (var ent in barBillExport)
                {
                    row = new Row();

                    row.Append(
                        ConstructCell(ent.Name.ToString(), CellValues.String, false),
                        ConstructCell((ent.LastPaymentDate.ToString().Length > 0) ? ent.LastPaymentDate.ToString() : "", CellValues.String, false),
                        ConstructCell((ent.LastPayment.ToString().Length > 0) ? ent.LastPayment.ToString() : "", CellValues.String, false),
                        ConstructCell((ent.TotalBalance.ToString().Length > 0) ? ent.TotalBalance.ToString() : "", CellValues.String, false));
                    sheetData.AppendChild(row);
                }

                worksheetPart.Worksheet.Save();
            }
            return ms.ToArray();
        }
    }

EDIT 编辑

Front End Service: 前端服务:

    createExcelDocument(model: BillList[]): any {
    return this.http.post(this.getBarBillsUrl + "/CreateExcelDocument", model)
        .map(this.helper.extractData)
        .catch(this.helper.handleError);
}

I am aware that the mapper does not need to be there. 我知道映射器不需要在那里。 But im keeping it there should i need to bring the byte array through to the front and go from there. 但是我将其保留在那里应该将字节数组传递到前面并从那里开始。

Any direction or guidance on the matter would be greatly appreciated. 对此事的任何指导或指导将不胜感激。

Thanks. 谢谢。

Solution Found for those interested or facing a similar issue(Please see below answers for author) 为有兴趣或面临类似问题的人找到解决方案(请参阅以下作者答案)

I added the { responseType: ResponseContentType.Blob } to the service call in TypeScript. 我将{ responseType: ResponseContentType.Blob }到TypeScript中的服务调用中。

It then returned me a blob of the spreadsheet. 然后,它给我返回了电子表格的内容。 From there, within the typescript i ran it through another method: 从那里,我在打字稿中通过另一种方法运行它:

    private saveAsBlob(data: any) {
    const year = this.today.getFullYear();
    const month = this.today.getMonth();
    const date = this.today.getDate();
    const dateString = year + '-' + month + '-' + date;

    const file = new File([data], 'BarBill ' + dateString + '.xlsx',
        { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });

    FileSaver.saveAs(file);
}

To then get my file to download client side. 然后获取我的文件以下载客户端。

Thanks very much to all. 非常感谢大家。 Especially the author of the answer. 尤其是答案的作者。

You need to tell Angular that the response is not JSON format , and so it will not try to parse it. 您需要告诉Angular响应不是JSON格式,因此它不会尝试解析它。 Try changing your code to: 尝试将代码更改为:

  createExcelDocument(model: BillList[]): any {
    return this.http.post(this.getBarBillsUrl + "/CreateExcelDocument", 
            model,  { responseType: ResponseContentType.Blob })
        .map(this.helper.extractData)
        .catch(this.helper.handleError);
}

The above code for binary format, but for excel files you should use this below code: 上面的代码为二进制格式,但是对于excel文件,您应该使用以下代码:

const httpOptions = {
      headers: new HttpHeaders({ 'responseType':  'ResponseContentType.Blob',
      'Content-Type':  'application/vnd.ms-excel'})};

  createExcelDocument(model: BillList[]): any {
    return this.http.post(this.getBarBillsUrl + "/CreateExcelDocument", 
            model, httpOptions )
        .map(this.helper.extractData)
        .catch(this.helper.handleError);
}

Your "return ms.ToArray();" 您的“返回ms.ToArray();” line needs to move inside the using and possibly add "document.Close();": 行需要在使用中移动,并可能添加“ document.Close();”:

public byte[] createExcelSpreadsheet(List<BarBillList> barBillExport)
{
    DateTime today = DateTime.Today;
    using (MemoryStream ms = new MemoryStream())
    {
        using (SpreadsheetDocument document = SpreadsheetDocument.Create(ms, SpreadsheetDocumentType.Workbook))
        {
            //Creating the initial document
            ...

            //Styling the doucment
            ...

            //Adding width to the columns
            ...

            //Creating the worksheet part to add the data to
            ...

            SheetData sheetData = worksheetPart.Worksheet.AppendChild(new SheetData());

            //Creating the first Header Row
            ...

            //Appending the data into their respective columns 
            foreach (var ent in barBillExport)
            {
                ...
            }

            worksheetPart.Worksheet.Save();
            document.Close();
            return ms.ToArray();
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM