Question

The below code which uses npoi to create excel documents displays images in open office calc but not in excel.

If i open the doc in calc and save the document and then open the document in excel i can then see the images in excel.

Here is the code.

  public static byte[] CreateExcel(CampaignViewModel viewModel, string fileName)
    {

        byte[] output;

        using (FileStream fs = new FileStream(HttpContext.Current.Server.MapPath(@"\Data\templates\NPOITemplate.xls"), FileMode.Open, FileAccess.ReadWrite))
        {

            var templateWorkbook = new HSSFWorkbook(fs, true);
            var sheet = templateWorkbook.GetSheet("Sheet1");
            var patriarch = sheet.CreateDrawingPatriarch();
            var leftFieldHeaders = CsvHelper.GetMatrixAllLeftFields();
            var productHeaders = CsvHelper.GetMatrixProducts(viewModel.ProductCampaigns);
            var totalCols = leftFieldHeaders.Count + productHeaders.Count;
            var colWidth = 5000;
            for (int i = 0; i < totalCols; i++)
            {
                sheet.SetColumnWidth(i, colWidth);
            }

            var imageRow = sheet.CreateRow(0);
            imageRow.Height = 2000;
            var imageCellCount = 0;
            foreach (var header in leftFieldHeaders)
            {
                imageRow.CreateCell(imageCellCount).SetCellValue("");
                imageCellCount++;
            }

            foreach (var product in viewModel.ProductCampaigns)
            {
                try
                {
                    var anchor = new HSSFClientAnchor(0, 0, 0, 0, imageCellCount, 0, imageCellCount, 0);
                    anchor.AnchorType = 2;
                    var path = HttpContext.Current.Server.MapPath(product.Product.ImageThumbUrl);
                    var picture = patriarch.CreatePicture(anchor, LoadImage(@path, templateWorkbook));

                    picture.Resize();
                    picture.LineStyle = HSSFPicture.LINESTYLE_SOLID;
                }
                catch (Exception)
                {

                }
                imageCellCount++;
            }


            using (MemoryStream ms = new MemoryStream())
            {
                templateWorkbook.Write(ms);
                output = ms.ToArray();
            }
        }
        return output;
    }

    public static int LoadImage(string path, HSSFWorkbook wb)
    {
        try
        {
            var file = new FileStream(path, FileMode.Open, FileAccess.ReadWrite);
            var buffer = new byte[file.Length];
            file.Read(buffer, 0, (int)file.Length);
            return wb.AddPicture(buffer, PictureType.JPEG);
        }
        catch (Exception)
        {
            return 0;
        }

    }
Was it helpful?

Solution

i've resolved the above in a round about way. Turns out i didn't really need to use the template and could just create the xls from scratch. This add's a bit more meta data to the file which i suspect was the issue

public static byte[] CreateExcel2(CampaignViewModel viewModel, ICollection<DeliveryPoint> deliveryPoints, string fileName)
{
    FileContentResult fileContentResult;
    byte[] output;
    var matrixCampaignLines = viewModel.MatrixCampaignLines;

    HSSFWorkbook hssfworkbook = new HSSFWorkbook();
    DocumentSummaryInformation dsi = PropertySetFactory.CreateDocumentSummaryInformation();
    dsi.Company = "NPOI Team";
    hssfworkbook.DocumentSummaryInformation = dsi;
    ////create a entry of SummaryInformation
    SummaryInformation si = PropertySetFactory.CreateSummaryInformation();
    si.Subject = "NPOI SDK Example";
    hssfworkbook.SummaryInformation = si;
    var sheet = hssfworkbook.CreateSheet("Sheet1");

    var patriarch = sheet.CreateDrawingPatriarch();
    var leftFieldHeaders = (viewModel.Campaign.EnableNameOnCampaign) ? CsvHelper.GetMatrixAllLeftFields() : CsvHelper.GetMatrixAllLeftFieldsWithoutName();
    var productHeaders = CsvHelper.GetMatrixProducts(viewModel.ProductCampaigns);
    var totalCols = leftFieldHeaders.Count + productHeaders.Count;
    var colWidth = 5000;
    for (int i = 0; i < totalCols; i++)
    {
        sheet.SetColumnWidth(i, colWidth);
    }

    var imageRow = sheet.CreateRow(0);
    imageRow.Height = 2000;
    var imageCellCount = 0;
    foreach (var header in leftFieldHeaders)
    {
        imageRow.CreateCell(imageCellCount).SetCellValue("");
        imageCellCount++;
    }

    foreach (var product in viewModel.ProductCampaigns)
    {
        try
        {
            var anchor = new HSSFClientAnchor(0, 0, 0, 0, imageCellCount, 0, imageCellCount, 0);
            anchor.AnchorType = 2;
            var path = HttpContext.Current.Server.MapPath(product.Product.ImageThumbUrl);
            var picture = patriarch.CreatePicture(anchor, LoadImage(@path, hssfworkbook));

            picture.Resize();//Comment this line if your code crashes.

            picture.LineStyle = HSSFPicture.LINESTYLE_SOLID; might not
        }
        catch (Exception)
        {

        }
        imageCellCount++;
    }

    using (MemoryStream ms = new MemoryStream())
    {
        hssfworkbook.Write(ms);
        output = ms.ToArray();
    }

    return output;
}

public static int LoadImage(string path, HSSFWorkbook wb)
{
    try
    {
        var file = new FileStream(path, FileMode.Open, FileAccess.Read);
        var buffer = new byte[file.Length];
        file.Read(buffer, 0, (int)file.Length);
        return wb.AddPicture(buffer, PictureType.JPEG);
    }
    catch (Exception)
    {
        return 0;
    }
}

OTHER TIPS

I got it right now.

I am using

try
            {

                ISheet sheet = templateWorkbook.GetSheet(sheetName);

                HSSFPatriarch patriarch = (HSSFPatriarch)sheet.CreateDrawingPatriarch();
                //create the anchor
                HSSFClientAnchor anchor;
                anchor = new HSSFClientAnchor(0, 0, 255, 255, 
                            start.Col, start.Row, end.Col, end.Row);
                anchor.AnchorType = 2;
                patriarch.CreatePicture(anchor, 
                                            LoadImage(imagePath, templateWorkbook));
            }
            catch (IOException ioe)
            {

            }

and LoadImage() method which returns path from the server.

Use this one. It runs fine.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top