项目总结【Excel中附件导出和导入】
公司两年前开发了一个项目电子平台,其中有一个模块是"项目问题清单",这个模块主要是让工程师记录项目的问题并跟踪,但是由于很多工程师不能在外网访问和录入表单时不够方便,所以用户提出了采用Excel导入功能。
这个问题清单主要功能有以下几点:
1.表结构是主从表关系,一个问题对应对个行动计划
2.一个问题中可以插入图片和附件
3.邮件提醒功能
4.允许将问题清单导入和导出(图片和附件必须跟上)
其中,最为纠结的是Excel中插入或导出附件这个功能。
最新的解决方案是用NPOI方式来操作,但是经分析,NPOI仅支持图片的导出,虽然有返回图片的对象,但是不能获取到指定单元格的图片,还有一个就是不支持2007和附件的插入
后来采用了DocumentFormat.OpenXml.dll这个东西。
以下具体讲讲这个中间的过程。
1.用Open Xml SDK 2.0将做好的模板生成代码,对代码分析和封装
说说其中的对象:SharedStringTablePart 共享数据部件
DrawingsPart 图片部件
ThemePart 主题部件
WorkbookStylesPart 样式部件
WorksheetPart sheet部件
VmlDrawingPart 绘图对象
EmbeddedPackagePart 嵌入包部件
2.导出遇到的问题
2.1 导出的图片自动旋转180了,主要修改这段代码 A.Transform2D transform2D = new A.Transform2D()即可;
2.2 附件.pptx次序颠倒,最后一个附件跑到第一个位置了,研究发现有一段是拼接字符串的东东,代码封装如下:
1 private void GenerateVmlDrawingPart1Content(VmlDrawingPart vmlDrawingPart1, DataTable dt)2 {3 int tmpInt = 1026;//默认种子附件编号4 System.Xml.XmlTextWriter writer = new System.Xml.XmlTextWriter(vmlDrawingPart1.GetStream(System.IO.FileMode.Create), System.Text.Encoding.UTF8);5 StringBuilder str = new StringBuilder();6 str.Append("<xml xmlns:v=\"urn:schemas-microsoft-com:vml\"\r\n xmlns:o=\"urn:schemas-microsoft-com:office:office\"\r\n xmlns:x=\"urn:schemas-microsoft-com:office:excel\">\r\n <o:shapelayout v:ext=\"edit\">\r\n <o:idmap v:ext=\"edit\" data=\"1\"/>\r\n </o:shapelayout><v:shapetype id=\"_x0000_t75\" coordsize=\"21600,21600\" o:spt=\"75\"\r\n o:preferrelative=\"t\" path=\"m@4@5l@4@11@9@11@9@5xe\" filled=\"f\" stroked=\"f\">\r\n <v:stroke joinstyle=\"miter\"/>\r\n <v:formulas>\r\n <v:f eqn=\"if lineDrawn pixelLineWidth 0\"/>\r\n <v:f eqn=\"sum @0 1 0\"/>\r\n <v:f eqn=\"sum 0 0 @1\"/>\r\n <v:f eqn=\"prod @2 1 2\"/>\r\n <v:f eqn=\"prod @3 21600 pixelWidth\"/>\r\n <v:f eqn=\"prod @3 21600 pixelHeight\"/>\r\n <v:f eqn=\"sum @0 0 1\"/>\r\n <v:f eqn=\"prod @6 1 2\"/>\r\n <v:f eqn=\"prod @7 21600 pixelWidth\"/>\r\n <v:f eqn=\"sum @8 21600 0\"/>\r\n <v:f eqn=\"prod @7 21600 pixelHeight\"/>\r\n <v:f eqn=\"sum @10 21600 0\"/>\r\n </v:formulas>\r\n <v:path o:extrusionok=\"f\" gradientshapeok=\"t\" o:connecttype=\"rect\"/>\r\n <o:lock v:ext=\"edit\" aspectratio=\"t\"/>\r\n </v:shapetype>");7 str.Append("<v:shape id=\"_x0000_s1025\" type=\"#_x0000_t75\" style=\'position:absolute;\r\n margin-left:215.25pt;margin-top:2.25pt;width:62.25pt;height:39pt;z-index:1\'\r\n filled=\"t\" fillcolor=\"window [65]\" stroked=\"t\" strokecolor=\"windowText [64]\"\r\n o:insetmode=\"auto\">\r\n <v:fill color2=\"window [65]\"/>\r\n <v:imagedata o:relid=\"rPPT_title\" o:title=\"\"/>\r\n <x:ClientData ObjectType=\"Pict\">\r\n <x:SizeWithCells/>\r\n <x:Anchor>\r\n 4, 3, 0, 3, 4, 86, 0, 55</x:Anchor>\r\n <x:CF>Pict</x:CF>\r\n </x:ClientData>\r\n </v:shape>");8 for (int row = 0; row < dt.Rows.Count; row++)9 {10 if (dt.Rows[row]["FILE_PPTX_PATH"].ToString() != "")11 {12 str.AppendFormat("<v:shape id=\"_x0000_s{0}\" type=\"#_x0000_t75\" style=\'position:absolute;\r\n margin-left:596.25pt;margin-top:{1}pt;width:53.25pt;height:35.25pt;\r\n z-index:{3}\' filled=\"t\" fillcolor=\"window [65]\" stroked=\"t\" strokecolor=\"windowText [64]\"\r\n o:insetmode=\"auto\">\r\n <v:fill color2=\"window [65]\"/>\r\n <v:imagedata o:relid=\"rPPT_details\" o:title=\"\"/>\r\n <x:ClientData ObjectType=\"Pict\">\r\n <x:SizeWithCells/>\r\n <x:Anchor>\r\n 10, 5, {2}, 5, 10, 76, {2}, 52</x:Anchor>\r\n <x:CF>Pict</x:CF>\r\n </x:ClientData>\r\n </v:shape>", tmpInt, (69.75 + (42.75 * row)).ToString(), row + 2, row + 2);13 tmpInt++;14 }15 }16 str.Append("</xml>");17 writer.WriteRaw(str.ToString());18 writer.Flush();19 writer.Close();20 }
纠结个的地方 shape id=\"_x0000_s{0}\"和<x:Anchor>\r\n 10, 5, {2}, 5, 10, 76, {2}, 52</x:Anchor>\r\
shape 嵌入的东西是以1025开始的,1026表示第二个...Anchor 记录附件的位置,个人理解左上角是1,3 右下角是5,7(导入的时候要读入该内容,判断是否有附件)
所有的附件采用用同一个图片
3.导入遇到的问题
3.1Excel中的附件无法抓取,后来解析<x:Anchor>这个东西才得以判断当前单元格是否有附件
3.2附件与Uri对应不上,即shape 与Uri 没有直接的关系,后来分析需要这个OleObjects对象
另附上部分代码:
1 //获取单元格中的值2 private String GetValue(Cell cell, SharedStringTablePart stringTablePart)3 {4 if (cell == null)5 {6 return "";//7 }8 if (cell.ChildElements.Count == 0)9 {10 return "";11 }12 String value = cell.CellValue.InnerText;13 if ((cell.DataType != null) && (cell.DataType == CellValues.SharedString))14 {15 value = stringTablePart.SharedStringTable.ChildElements[Int32.Parse(value)].InnerText;16 }17 return value;18 }
1 //Excel抓取图片2 private void ImportImg(WorksheetDrawing dp, string _Embed, string filePath)3 {4 ImagePart ip = dp.DrawingsPart.Parts.Single(c => c.RelationshipId == _Embed).OpenXmlPart as ImagePart;5 //imgExtension = System.IO.Path.GetExtension(ip.Uri.ToString());6 using (Stream stream = ip.GetStream(FileMode.Open, FileAccess.Read))7 {8 //string path = ip.Uri.OriginalString;//图片路径9 using (BinaryReader reader = new BinaryReader(stream))10 {11 byte[] buffer = new byte[reader.BaseStream.Length];12 reader.Read(buffer, 0, Convert.ToInt32(buffer.Length));13 //string base64String = Convert.ToBase64String(buffer);14 15 using (MemoryStream streamBitmap = new MemoryStream(buffer))16 {17 Bitmap bitImage = new Bitmap((Bitmap)System.Drawing.Image.FromStream(streamBitmap));18 bitImage.Save(filePath, bitImage.RawFormat);19 bitImage.Dispose();20 //Bitmap tmpbmp = new Bitmap(bitImage.Width, bitImage.Height);21 //using(Graphics g = Graphics.FromImage(tmpbmp))22 //{23 //g.DrawImage(bitImage, 0, 0);24 //tmpbmp.Save(filePath, bitImage.RawFormat);25 //}26 //bitImage.Dispose();27 //tmpbmp.Dispose();28 }29 }30 }31 }
//是否存在附件 private void IsAttaach(ref EmbeddedPackagePart emb, string rowIndex, string colIndex) {var item = (from a in lt_Dictionary join b in lt_AttachRef on a.Shapeid equals b.Shapeidwhere a.RowIndex == rowIndex && a.ColIndex == colIndexselect new { b.Uri }).SingleOrDefault();if (item != null) { emb = item.Uri; } } //Excel中抓取附件 private void ImportPptx(EmbeddedPackagePart Uri, string filePath) {using (Stream stream = Uri.GetStream(FileMode.Open, FileAccess.Read)) {using (BinaryReader reader = new BinaryReader(stream)) {byte[] buffer = new byte[reader.BaseStream.Length]; reader.Read(buffer, 0, Convert.ToInt32(buffer.Length)); FileStream fs = new FileStream(filePath, FileMode.Create); fs.Write(buffer, 0, buffer.Length); fs.Flush(); fs.Close(); } } }
这段是定位分析附件的
//将vml文本加载到xml中,获取行列的定位 VmlDrawingPart vml = documentPack.WorkbookPart.WorksheetParts.First().VmlDrawingParts.First(); Stream workbookstr = vml.GetStream(); System.Xml.XmlDocument doc = new System.Xml.XmlDocument(); doc.Load(workbookstr);string[] strArr = doc.InnerText.Replace("\r\n", "|").Replace("Pict", "").Remove(0, 1).Trim().Split('|'); for (int i = 0; i < doc.FirstChild.ChildNodes.Count; i++) {if (doc.FirstChild.ChildNodes[i].Name == "v:shape") {var item = doc.FirstChild.ChildNodes[i];string[] str = item.InnerText.Replace("\r\n", "|").Trim().Split('|')[1].Split(','); lt_Dictionary.Add(new DictionaryClass { Shapeid = item.Attributes["id"].Value.Split('s').Last(), ColIndex = str[0].Trim(), RowIndex = str[2].Trim() }); } }
小结:
1.主要用到了附件与Base64String 互转
/// <summary>///Author:严智远 Remark:将流填充到ImagePart对象中 Date:2012-02-18/// </summary>/// <param name="imagePart3"></param> private void GenerateImagePartContent(ImagePart imagePart, string filePath) {//将图片转换成字符 System.Drawing.Bitmap bmp = (System.Drawing.Bitmap)System.Drawing.Image.FromFile(HttpContext.Current.Server.MapPath("~")+filePath); MemoryStream stream = new MemoryStream(); bmp.Save(stream, System.Drawing.Imaging.ImageFormat.Bmp); stream.Position = 0;byte[] buff = new byte[stream.Length]; stream.Read(buff, 0, (int)stream.Length); stream.Close(); System.IO.Stream data = GetBinaryDataStream(System.Convert.ToBase64String(buff, 0, buff.Length)); imagePart.FeedData(data); data.Close(); }
2.IO操作、linq操作对象
3..vml后缀文件的了解
4.如何查看及分析问题
转载于:https://www.cnblogs.com/yanzhiyuan928/archive/2012/03/09/2387784.html
项目总结【Excel中附件导出和导入】相关推荐
- .net excel导入mysql_.NET Core使用NPOI将Excel中的数据批量导入到MySQL - 追逐时光者 - 博客园...
前言: 在之前的几篇博客中写过.NET Core使用NPOI导出Word和Excel的文章,今天把同样我们日常开发中比较常用的使用Excel导入数据到MySQL数据库中的文章给安排上.与此同时还把NP ...
- matlab如何在word中插入多个表格,怎么把excel中的数据批量导入到word中的表格中《不同表格间的数据导入》...
如何将excel表格中大量数据导入matlab中并作图 工具:MATLAB.office excel 将待导入的矩阵结构据录入Excel中,录入时注意行列原矩阵一一对应. 录入完以后保存数据,为了后续 ...
- word录入表单数据 java 导入系统,java导入excel | 怎么把excel中的数据批量导入到word中的表格中...
用javascript怎么实现把excel中的数据批量导入到数据库表中 这个js不能直接实现吧 我们程序用到 先读取excel内容转换成数组 然后放到页面上 再提交表单 储存 MySql如何批量添加数 ...
- matlab输入excel高版本,『matlab读取excel指定列』excel中大量数据如何导入matlab当中?超过1000个数据无法一个一个输入...
如何将excel表格中大量数据导入matlab中并作图 哈哈,选我吧!使用xlsread函数体的语法你在帮助里面搜索xlsread就可以了.我要是现在回答也接翻译帮助文件.xlsread的参数有文件表 ...
- 如何在ex表格导入php_怎么使用php把表格中的数据导入到excel中,php如何快速导入excel表格数据...
php怎么导入大量数据的excel php导出数据的Excel: PHP从数据库分多次读取100万行记录,和分将100万入文本文件都没问题 Excel可以支100万行记录,Excel 2003最大支持 ...
- excel中联系人转换为csv导入手机出现乱码的解决方法
解决方式可直接调至文末黑体加粗加大字号. 同事要举行一个培训会议,需要联系各单位的人员,但是所有人员的单位.姓名.手机号都是存在excel里的.一个个存入手机太麻烦,数量太多会累死人.于是找我帮忙.. ...
- ISA Server 2004 中的导出、导入和备份功能
Microsoft Internet Security and Acceleration (ISA) Server 2004 包含导出和导入功能,您可使用这一功能将 ISA Server 配置参数保存 ...
- Excel中 使用链接 批量导入图片
■前言 我之前看到很多使用VBA方式导入图片的. 今天发现,使用复制链接这种方式,也可以导入图片. ■导入方法 <table><img src="C:\MyPicture\ ...
- poi导出excel中附件超链接
记录一下 参考了一些博客 https://blog.csdn.net/oTianKongLan123/article/details/106903234 https://blog.csdn.net/s ...
- MySQL导入Excel报1406_关于mysql 导入excel 中 数据不全或导入不了的 处理办法(工具sqlyong)借鉴经验...
文章作者:姜南(Slyar)文章来源:Slyar Home (www.slyar.com) 转载请注明,谢谢合作. 之前发了<表达式变量批量替换器 batchSQL>这篇文章,有童鞋说导入 ...
最新文章
- 病虫害模型算法_基于深度学习的目标检测算法综述
- 【 English 】与个人品质有关的英语词汇
- nodejs如何实现ajax,nodejs使用静态服务器处理ajax
- android 学习随笔十六(广播 )
- pyqt生成 android,PyQt on Android
- jlabel字怎么变化_疫情在家烦躁不如学习怎样练好字吧
- Java关键字finally
- C# 根据年、月、周、星期获得日期等
- JNI开发笔记(五)--JNI语法总结
- 使用Forms验证存储用户自定义信息
- request的获取路径用法小结
- windows7系统适合哪个python_windows7如何下载python系统
- 大型网吧网络系统设计详细方案(转)
- 王欣复出后的第一款产品
- python 如何匹配一撇字符_使用Python正则表达式解析斜杠和撇号
- C++:应用有限差分法求解随时间变化 平流方程 ut = - c * ux 在一个空间维度上,与 恒定速度,使用FTCS方法,正向时间差, 居中空间差(附完整源码)
- 技术周刊(第10期):新技术又来了?
- 生产力、商业价值和敏捷
- 李笑来,那个一顿饭点8条鲈鱼的人
- 三星S9勃艮第红如何为女人打造“第四维”魅力?