.Net Core Excel 带图片的导出

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

九叶重楼二两,冬至蝉蛹一钱,煎入隔年雪,可医世人相思苦疾。

可重楼七叶一枝花,冬至何来蝉蛹,雪又怎能隔年,原是相思无解。

殊不知,夏枯即为九叶重楼,掘地三尺寒蝉现,除夕子时雪,落地已隔年。

过了离别时,相思亦可解。

.net中导出的功能估计是各大系统比不缺少的功能,本文主要记录Excel带图片导出功能中的一些注意事项。 本文导出Excel是用EPPlus实现的。

这里就直接上代码了。。。

   #region 生成Excel
                string sFileName = DataParseHelper.GetDateYMDHMS(DateTime.Now) + ".xlsx";
                string path = AppSettingsReader.UploadResourcePath + "/OutPutExcel/统计/";
                if (!Directory.Exists(path))
                {
                    Directory.CreateDirectory(path);
                }
                FileInfo file = new FileInfo(path + sFileName);

                using (ExcelPackage package = new ExcelPackage(file))
                {
                    int index = 0;
                    try
                    {
                        #region 添加worksheet1
                        ExcelWorksheet worksheet = package.Workbook.Worksheets.Add("固定资产");
                        worksheet.PrinterSettings.PaperSize = ePaperSize.A3;//纸张大小
                        worksheet.PrinterSettings.Orientation = eOrientation.Landscape;//页面横向
                        worksheet.DefaultRowHeight = 60;
                        worksheet.DefaultColWidth = 15;
                        //设置列宽
                        worksheet.Column(++index).Width = 5;
                    
                        worksheet.Column(++index).Width = 13;
                        worksheet.Column(++index).Width = 13;
                        worksheet.Column(++index).Width = 15;
                        //worksheet.Column(++index).Width = 15;//注释后下面设置图片的位置才可以
                        worksheet.Cells[1, 1, 1, index + 1].Merge = true;
                        worksheet.Cells[1, 1].Value = companyName + "_______________统计明细表";
                        worksheet.Row(1).Style.Font.Bold = true;
                        worksheet.Row(1).Style.HorizontalAlignment = ExcelHorizontalAlignment.Center;   //居中 
                        worksheet.Row(1).Style.VerticalAlignment = ExcelVerticalAlignment.Center;   //居中 
                        worksheet.Row(1).Style.Font.Size = 14;   //字体大小
                        worksheet.Row(1).Style.Font.Name = "宋体";
                        worksheet.Row(1).Height = 40;    //表头行高
                        worksheet.Cells.Style.WrapText = true;

                        //添加头
                        index = 0;
                        worksheet.Cells[2, ++index].Value = "序号";
                        worksheet.Cells[2, ++index].Value = "资产类别";
                        worksheet.Cells[2, ++index].Value = "资产名称";
                        worksheet.Cells[2, ++index].Value = "SN号";                       
                        worksheet.Cells[2, ++index].Value = "备注";
                        worksheet.Row(2).Style.Font.Bold = true;  //字体为粗体                                     worksheet.Row(2).Style.HorizontalAlignment = ExcelHorizontalAlignment.Center;
                        worksheet.Row(2).Style.VerticalAlignment = ExcelVerticalAlignment.Center;
                        worksheet.Row(2).Style.Font.Size = 12;
                        worksheet.Row(2).Style.Font.Name = "宋体";
                        worksheet.Cells[2, 1, 2, index].Style.Fill.PatternType = ExcelFillStyle.Solid;

                        //边框
                        worksheet.Cells[1, 1, returnList.Count + 3, index].Style.Border.Top.Style = ExcelBorderStyle.Thin;
                        worksheet.Cells[1, 1, returnList.Count + 3, index].Style.Border.Bottom.Style = ExcelBorderStyle.Thin;
                        worksheet.Cells[1, 1, returnList.Count + 3, index].Style.Border.Left.Style = ExcelBorderStyle.Thin;
                        worksheet.Cells[1, 1, returnList.Count + 3, index].Style.Border.Right.Style = ExcelBorderStyle.Thin;

                        int i = 0;
                        int allcheck = 0;
                        int alllistcount = 0;
                        for (int j = 0; j < returnList.Count; j++)
                        {
                            AssetInfoOtherView item = returnList[j];
                            index = 0;

                            List<AssetInfoOtherView> chilalist = returnList.Where(x => x.AssetParentId == item.AssetId).ToList();
                            if (chilalist.Count > 0)//说明有子集 需要合并单元格
                            {
                                worksheet.Cells[i + 3, 2, i + 3 + chilalist.Count, 2].Merge = true;
                                worksheet.Cells[i + 3, 3, i + 3 + chilalist.Count, 3].Merge = true;
                                worksheet.Cells[i + 3, 4, i + 3 + chilalist.Count, 4].Merge = true;
                            }
                            worksheet.Row(i + 3).Height = 60;
                            worksheet.Row(i + 3).Style.HorizontalAlignment = ExcelHorizontalAlignment.Left;
                            worksheet.Row(i + 3).Style.VerticalAlignment = ExcelVerticalAlignment.Center;
                            worksheet.Cells[i + 3, ++index].Value = i + 1;
                            worksheet.Cells[i + 3, ++index].Value = item.AssetTypeName;
                            worksheet.Cells[i + 3, ++index].Value = item.AssetName;
                            worksheet.Cells[i + 3, ++index].Value = item.AssetCode;    
                            #region 
                            if (containImg == "1")
                            {
                                try
                                {
                                    if (string.IsNullOrEmpty(item.CheckImgUrl))//图片为空
                                    {
                                        worksheet.Cells[i + 3, ++index].Value = "";// item.CheckImgUrl;
                                    }
                                    else
                                    {
                                        string imgpath = AppSettingsReader.UploadResourceUrl + item.CheckImgUrl;
                                        Image img = Image.FromStream(WebRequest.Create(imgpath).GetResponse().GetResponseStream());

                                        int toWidth = 1048;
                                        Image imgmid;
                                        if (img.Width > toWidth || img.Height > toWidth)//图片过大的情况下需要压缩
                                        {
                                            imgpath = CompressImage(imgpath, toWidth, item.CheckImgUrl);
                                            imgmid = Image.FromFile(imgpath);
                                        }
                                        else
                                        {
                                            imgmid = img;
                                        }
                                        if (imgmid.Width > imgmid.Height)//宽图显示失败,所以做下旋转后再显示
                                        {
                                            Image Roimg = RotateImg(imgmid, 90);//旋转后直接AddPicture报错,只能旋转后再次保存,读取保存后的图片。待优化。
                                                                                //Random rd = new Random();
                                                                                //int sindex = imgpath.LastIndexOf('/');
                                                                                //string newpath = imgpath.Substring(0, sindex + 1) + rd.Next() + ".jpg";

                                            //保存缩略图
                                            Random rd = new Random();
                                            string savepath = AppSettingsReader.UploadResourcePath + "/OutPutExcel/Temp/" + rd.Next() + ".jpg";
                                            Roimg.Save(savepath, ImageFormat.Jpeg);

                                            Image newimg = Image.FromFile(savepath);

                                            ExcelPicture pic = worksheet.Drawings.AddPicture(i.ToString(), newimg);
                                            pic.SetPosition(i + 3 - 1, 0, ++index - 1, 0);//设置的位置是以0为开始索引的,我们实际表中是以1为开始索引的,所以需要减1                      
                                            pic.SetSize(80, 80);

                                        }
                                        else
                                        {
                                            string[] arrpath = imgpath.Split('.');
                                            if (arrpath.Length > 1)
                                            {
                                                Image newimg;
                                                if (arrpath[arrpath.Length - 1] != "jpg")
                                                {
                                                    imgpath = ImgOtherToJpg(imgpath, item.CheckImgUrl);//实际项目中有其他格式的图片,会导致导出报错,固此处转换成jpg的
                                                    newimg = Image.FromFile(imgpath);
                                                }
                                                else
                                                {
                                                    newimg = imgmid;
                                                }

                                                ExcelPicture pic = worksheet.Drawings.AddPicture(i.ToString(), newimg);
                                                pic.SetPosition(i + 3 - 1, 0, ++index - 1, 0);//设置的位置是以0为开始索引的,我们实际表中是以1为开始索引的,所以需要减1                      
                                                pic.SetSize(80, 80);
                                            }
                                            else
                                            {
                                                worksheet.Cells[i + 3, ++index].Value = "";// item.CheckImgUrl;
                                            }
                                        }

                                    }
                                }
                                catch (Exception ex)
                                {
                                    LogHelper.CurrentLogger.Error(ex.Message, ex);
                                    worksheet.Cells[i + 3, ++index].Value = "图片异常";// item.CheckImgUrl;
                                }
                            }
                            #endregion
                            alllistcount += item.AssetCount;
                            i++;
                        }
                        #endregion
                        package.Save();
                    }
                    catch (Exception ex)
                    {
                        LogHelper.CurrentLogger.Error(ex.Message, ex);
                        resultModel = ResponseModel.EasyUiPageListException(0, null, ex.Message);
                        return this.Json(resultModel);
                    }
                }
                #endregion
复制代码

## Attention

1、图片的表格头不需要设置长度,否则会不显示的;

2、图片在表格中的位置是以0为开始索引的,我们实际表中是以1为开始索引的,所以记得索引减1;

3、获取的图片不能过大,过大会影响导出速度;

4、获取的图片最好是竖图,横图的话宽度不能过大,具体的数值没有测试,我是把超过1024的就旋转了;

5、图片的格式最好是jpg,其他的有可能会报错。

附上图片的处理方法

  #region 无损压缩图片
        /// <summary>
        /// 无损压缩图片
        /// </summary>
        /// <returns></returns>
        public string CompressImage(string sFile, int toWidth, string pathStr)
        {
            //Image initimage = Image.FromFile(sFile);

            Image initimage = Image.FromStream(WebRequest.Create(sFile).GetResponse().GetResponseStream());


            if (initimage.Width > toWidth || initimage.Height > toWidth)
            {
                int toHeight;
                if (initimage.Width > initimage.Height)
                {
                    toHeight = initimage.Height * toWidth / initimage.Width;
                }
                else
                {
                    toHeight = toWidth;
                    toWidth = initimage.Width * toHeight / initimage.Height;
                }

                //生成新图
                //新建一个bmp图片
                Image newimage = new Bitmap((int)toWidth, (int)toHeight);
                //新建一个画板
                Graphics newg = Graphics.FromImage(newimage);
                //设置质量
                newg.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
                newg.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
                //置背景色
                newg.Clear(Color.White);
                //画图
                newg.DrawImage(initimage, new Rectangle(0, 0, newimage.Width, newimage.Height), new Rectangle(0, 0, initimage.Width, initimage.Height), GraphicsUnit.Pixel);
                //保存缩略图
                Random rd = new Random();
                string savepath = AppSettingsReader.UploadResourcePath + "/OutPutExcel/Temp/" + rd.Next() + ".jpg";
                newimage.Save(savepath, System.Drawing.Imaging.ImageFormat.Jpeg);
                //释放资源
                newg.Dispose();
                newimage.Dispose();
                initimage.Dispose();
                return savepath;
            }
            else
            {
                return sFile;
            }
        }

        #endregion
复制代码
  #region 图片旋转
        public Image RotateImg(Image img, float angle)
        {
            //通过Png图片设置图片透明,修改旋转图片变黑问题。
            int width = img.Width;
            int height = img.Height;
            //角度
            Matrix mtrx = new Matrix();
            mtrx.RotateAt(angle, new PointF((width / 2), (height / 2)), MatrixOrder.Append);
            //得到旋转后的矩形
            GraphicsPath path = new GraphicsPath();
            path.AddRectangle(new RectangleF(0f, 0f, width, height));
            RectangleF rct = path.GetBounds(mtrx);
            //生成目标位图
            Bitmap devImage = new Bitmap((int)(rct.Width), (int)(rct.Height));
            Graphics g = Graphics.FromImage(devImage);
            g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.Bilinear;
            g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
            //计算偏移量
            Point Offset = new Point((int)(rct.Width - width) / 2, (int)(rct.Height - height) / 2);
            //构造图像显示区域:让图像的中心与窗口的中心点一致
            Rectangle rect = new Rectangle(Offset.X, Offset.Y, (int)width, (int)height);
            Point center = new Point((int)(rect.X + rect.Width / 2), (int)(rect.Y + rect.Height / 2));
            g.TranslateTransform(center.X, center.Y);
            g.RotateTransform(angle);
            //恢复图像在水平和垂直方向的平移
            g.TranslateTransform(-center.X, -center.Y);
            g.DrawImage(img, rect);
            //重至绘图的所有变换
            g.ResetTransform();
            g.Save();
            g.Dispose();
            path.Dispose();

            return devImage;
        }

        #endregion 
复制代码
  #region 图片格式转化成jpg
        public string ImgOtherToJpg(string StartPath, string pathStr)
        {
            //Image img = Image.FromFile(StartPath);
            Image img = Image.FromStream(WebRequest.Create(StartPath).GetResponse().GetResponseStream());


            using (var bmp = new Bitmap(img.Width, img.Height))
            {
                bmp.SetResolution(img.HorizontalResolution, img.VerticalResolution);

                using (var g = Graphics.FromImage(bmp))
                {
                    g.Clear(Color.White);
                    g.DrawImageUnscaled(img, 0, 0);
                }
                Random rd = new Random();
                string savepath = AppSettingsReader.UploadResourcePath + "/OutPutExcel/Temp/" + rd.Next() + ".jpg";
                bmp.Save(savepath, System.Drawing.Imaging.ImageFormat.Jpeg);


                return savepath;
            }
        }
        #endregion
复制代码

这样就能导出带图片的Excel,当然需要根据自己的表格设置合理的行高,不然容易变形。

目前最主要的还是速度问题,一旦超过几千张图片一起导出时就比较慢,后续再慢慢优化,先把任务完成再谈。(Ps:程序员的后续优化也不知道什么时候...)

猜你喜欢

转载自juejin.im/post/7016907065125765151