小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
九叶重楼二两,冬至蝉蛹一钱,煎入隔年雪,可医世人相思苦疾。
可重楼七叶一枝花,冬至何来蝉蛹,雪又怎能隔年,原是相思无解。
殊不知,夏枯即为九叶重楼,掘地三尺寒蝉现,除夕子时雪,落地已隔年。
过了离别时,相思亦可解。
.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:程序员的后续优化也不知道什么时候...)