处理Doc、Doc,Excel文件的学习总结- ExcelDataReader,DocX,Microsoft.Office.Interop.Word

时间:2024-03-05 15:48:41

ExcelDataReader
是一个非常轻量级和快速的库,用c#编写,用于读取Microsoft Excel文件(2.0-2007)。
支持的文件格式和版本
文件类型 Container Format File Format Excel Version(s)
.xlsx ZIP, CFB+ZIP OpenXml 2007 and newer
.xls CFB BIFF8 97, 2000, XP, 2003
98, 2001, v.X, 2004 (Mac)
.xls CFB BIFF5 5.0, 95
.xls - BIFF4 4.0
.xls - BIFF3 3.0
.xls - BIFF2 2.0, 2.2
.csv - CSV (All)

安装ExcelDataReader基本包以使用“低级” reader接口。兼容net20、net45、netstandard1.3和netstandard2.0。
安装ExcelDataReader.DataSet扩展包使用AsDataSet()方法来填充System.Data.DataSet的数据集。这也将拉入基本包。兼容net20、net45和netstandard2.0。

基本使用

using (var stream = File.Open(filePath, FileMode.Open, FileAccess.Read))
{
    // 自动检测格式,支持:
    //  - Binary Excel files (2.0-2003 format; *.xls)
    //  - OpenXml Excel files (2007 format; *.xlsx)
    using (var reader = ExcelReaderFactory.CreateReader(stream))
    {
        // 从1或2中选择一个:
        // 1. Use the reader methods
        do
        {
            while (reader.Read())
            {
                // reader.GetDouble(0);
            }
        } while (reader.NextResult());

        // 2. 使用AsDataSet扩展方法
        var result = reader.AsDataSet();

        //每个电子表格的结果在result. tables中
    }
}

读csv文件
使用ExcelReaderFactory.CreateCsvReader 而不是CreateReader 解析用逗号分隔值的纯文本流。
也可以看下配置选项:FallbackEncoding and AutodetectSeparators.

输入CSV总是完全解析一次,以设置FieldCount、RowCount、编码、分隔符(如果CSV缺少BOM且不是UTF8,则解析两次),然后在迭代行记录时再次解析。如果输入不能使用指定的编码进行解析,则会抛出System.Text.DecoderFallbackException异常
reader将所有CSV字段值作为字符串返回,并且不尝试将数据转换为数字或日期。这个调用者负责解释CSV数据。
使用读取器方法
AsDataSet()扩展方法是快速获取数据的方便助手,但并不总是可用或需要使用。IExcelDataReader扩展了System.Data.IDataReader and IDataRecord接口,用于在较低级别导航和检索数据。
最重要的读取器方法和属性。
Read() 从当前工作表中读取一行
NextResult() 将光标移到下一个工作表
ResultsCount 返回当前工作簿中的工作表数
Name 返回当前工作表的名称
CodeName 返回当前工作表的VBA代码名称标识符
FieldCount 返回当前工作表中的列数。
RowCount 返回当前工作表中的行数。这包括终端空行,否则将被AsDataSet()排除。当与AnalyzeInitialCsvRows一起使用时,在CSV文件中抛出InvalidOperationException。
HeaderFooter 返回带有有关页眉和页脚信息的对象,如果没有,则返回null。
MergeCells 返回当前工作表中合并的单元格范围数组。
RowHeight 返回当前行的可视高度(以点为单位)。如果该行被隐藏,则可能为0。
GetColumnWidth() 以字符单位返回列的宽度。如果该列被隐藏,则可能为0。
GetFieldType() 返回当前行的值的类型。总是Excel支持的类型之一:double、int、bool、DateTime、TimeSpan、string,如果没有值,则为null。
IsDBNull() 检查当前行的值是否为空。
GetValue() 从当前行返回一个值作为对象,如果没有值则返回null
GetDouble(), GetInt32(), GetBoolean(), GetDateTime(), GetString() 将当前行的一个值转换为它们各自的类型。
GetNumberFormatString() 返回包含当前行的值的格式化代码的字符串,如果没有值则返回null。请参阅下面的格式化部分。
GetNumberFormatIndex() 返回当前行的值的数字格式索引。164以下的索引值表示内置的数字格式,否则表示自定义数字格式
除非类型完全匹配,否则类型化Get*()方法将抛出InvalidCastException。

 CreateReader()配置选项

ExcelReaderFactory.CreateReader()、CreateBinaryReader()、CreateOpenXmlReader()、CreateCsvReader()方法接受一个可选的配置对象来修改reader的行为:

var reader = ExcelReaderFactory.CreateReader(stream, new ExcelReaderConfiguration()
{
    // 获取或者设置encoding 当输入的XLS缺失CodePage 记录或者当CSV缺失Bom并且不解析为UTF8。
    //默认是: cp1252 (XLS BIFF2-5 and CSV only)
    FallbackEncoding = Encoding.GetEncoding(1252),

    // 获取或设置用于打开受密码保护的工作簿的密码。
    Password = "password",

    // 获取或设置CSV分隔符候选数组。reader自动检测哪个最适合输入数据。 TAB | # 
    // (CSV only)
    AutodetectSeparators = new char[] { \',\', \';\', \'\t\', \'|\', \'#\' },

   //获取或设置一个值,该值指示在IExcelDataReader对象被释放后是否保持流打开。默认值:假
    LeaveOpen = false,

//获取或设置一个值,该值指示在CSV中要分析编码、分隔符和字段计数的行数。设置时,此选项使 IExcelDataReader.RowCount属性来抛出异常。默认值:0 -分析整个文件只有CSV,对其他没有影响格式)
    AnalyzeInitialCsvRows = 0,
});

AsDataSet()配置选项
AsDataSet()方法接受一个可选的配置对象来修改DataSet转换的行为:

var result = reader.AsDataSet(new ExcelDataSetConfiguration()
{
    // 获取或设置一个值,该值指示是否设置DataColumn.DataType属性.
    UseColumnDataType = true,

    // 获取或设置回调,以确定是否在DataSet中包含当前工作表。在ConfigureDataTable之前,每个Sheet调用一次。
    FilterSheet = (tableReader, sheetIndex) => true,

    // 获取或设置回调以获取数据表的配置选项。
    ConfigureDataTable = (tableReader) => new ExcelDataTableConfiguration()
    {
        // 获取或设置一个值,该值指示生成的列名的前缀。
        EmptyColumnNamePrefix = "Column",

        //获取或设置一个值,该值指示是否将数据中的行用作列名。
        UseHeaderRow = false,

        //获取或设置回调以确定哪一行是标题行。只在UseHeaderRow = true时调用。
        ReadHeaderRow = (rowReader) => {
            //跳过第一行使用第二行作为列的header
            rowReader.Read();
        },

        //获取或设置回调,以确定是否包括数据表中的当前行
        FilterRow = (rowReader) => {
            return true;
        },

        // 获取或设置回调,以确定是否在数据表中包含特定列。读取标题后,每列调用一次。
        FilterColumn = (rowReader, columnIndex) => {
            return true;
        }
    }
});

Formatting
ExcelDataReader 不直接支持格式化. 用户可以通过IExcelDataReader.GetNumberFormatString(i)获取单元格的数字格式字符串,并使用第三方的ExcelNumberFormat库进行格式化。

string GetFormattedValue(IExcelDataReader reader, int columnIndex, CultureInfo culture)
{
    var value = reader.GetValue(columnIndex);
    var formatString = reader.GetNumberFormatString(columnIndex);
    if (formatString != null)
    {
        var format = new NumberFormat(formatString);
        return format.Format(value, culture);
    }
    return Convert.ToString(value, culture);
}

处理Doc或者Docx

可以是用Microsoft.Office.Interop.Word组件库,需要依赖Office,并且使用还存在莫名的bug,不建议使用
推荐使用DocX-它不需要安装Microsoft Word或Office。就能直接使用。

What is DocX?
DocX是一个.NET 库,允许开发人员操作Word 2007/2010/2013文件,操作简单直观。DocX是快速、轻量级的,最好的是它不需要安装Microsoft Word或Office。
注:自2017年10月3日起新增一个主分支。如果您在更改之前使用这个项目,请阅读关于Classic分支的内容。
DocX是 .NET的Xceed word的免费开源版本。最初由Cathal Coffey撰写,由Przemyslaw Klys维护,现在由Xceed维护。从v1.5.0开始,这个免费的开源产品是在Xceed社区许可协议下提供的(用于非商业用途)。
当前,DocX和Xceed Words for Net的区别在于- Xceed Words for .NET
可以将Word文档转换为PDF吗
添加属性来将文本包装在图片/表格/形状周围
添加图片裁剪添加形状(现在是矩形)
添加文本框或包含文本的形状
从段落中获取形状
从段落中获取图表,并可以修改其类别/值
是否至少有两个版本先于DocX版本
订阅中包含专业技术支持吗
我还需要什么?
使用DocX所需要安装的是。net framework 4.0和Visual Studio 2010或更高版本,它们都是免费的。

DocX的主要特性是什么?
创建新的Word文档
修改Word文档
支持从Word2007及以上的.DOCX
并行修改多个文档以获得更好的性能
将模板应用于Word文档
连接文档,从一个文档到另一个文档重新创建部分
支持文档保护与密码或不带密码
设置文档的页边距和页面大小
设置行间距,缩进,文本方向,文本对齐
管理字体和字体大小
设置文本颜色,粗体,下划线,斜体,删除线,高亮显示
设置页码
创建sections

添加页眉或页脚,这些页眉或页脚可以在所有页面上都是相同的,或者在第一个页面上是唯一的,或者在奇数/偶数页面上是唯一的。可以包含图像,超链接和更多。
插入/修改段落。
插入/修改编号或项目符号列表。
插入/修改图片。翻转,旋转,复制,修改,调整大小。
插入/修改表。插入/删除行、列、更改方向、列宽、行高、边框、合并/删除单元格。
插入/修改格式化的方程或公式。
插入/修改书签。
插入/修改超链接。
插入/修改水平线。
插入/修改图表(条、线、饼图、3D图表)。设置颜色、标题、图例等。
查找、删除或替换文本。支持大小写敏感和正则表达式。
插入/修改核心属性或自定义属性,如作者、地址、主题、标题等。
插入目录。设置标题,更改格式。
插入/修改形状(目前为矩形)
更新文档字段

为什么要使用DocX?
DocX使创建和操作文档成为一项简单的任务。它不使用COM库,也不需要安装Microsoft Office。
下面这篇来自Cathal Coffey的博客比较了用来创建HelloWorld文档的代码:

Office Interop libraries,
OOXML SDK,
DocX

Advanced Examples
一步一步的指导创建一个公司的发票http://cathalscorner.blogspot.com/2009/08/docx-v1007-released.html
在多个文档之间并行替换文本 http://cathalscorner.blogspot.com/2010/12/replace-text-across-many-documents-in.html
以编程方式操作嵌入在文档中的图像http://cathalscorner.blogspot.com/2010/12/programmatically-manipulate-image.html
转换 DocX 为(.doc, .pdf, .html) http://cathalscorner.blogspot.com/2009/10/converting-docx-into-doc-pdf-html.html
更多信息可以在许可页面中找到。
商业许可证可以在Xceed购买。

这里重点讲操作Word中的Table-比如新增一行,新增多行等,在指定的行插入新行等

 1  public static void InsertRow(string fileName,int tableNum,int rowNum)
 2         {
 3             using (var document = DocX.Load(fileName))
 4             {
 5                 var table = document.Tables[tableNum];
 6                 //var row = table.Rows[rowNum];
 7                 table.InsertRow(rowNum);
 8                 document.Save();
 9             }
10         }
11         public static void InsertRowMults(string fileName, int tableNum, int rowNum,int rowCount)
12         {
13             using (var document = DocX.Load(fileName))
14             {
15                 var table = document.Tables[tableNum];
16                 for (int i = 0; i < rowCount; i++)
17                 {
18                     table.InsertRow(rowNum);
19                     rowNum++;
20                 }
21                 document.Save();
22             }
23         }
24         public static void InsertRowMultsWithFormat(string fileName, int tableNum, int rowNum, int rowCount)
25         {
26             using (var document = DocX.Load(fileName))
27             {
28                 var table = document.Tables[tableNum];
29                 for (int i = 0; i < rowCount; i++)
30                 {
31                     var row = table.Rows[rowNum];
32                     table.InsertRow(row, rowNum, true);
33                     rowNum++;
34                 }
35                 document.Save();
36             }
37         }
38         public static void InsertRowMultsWithFormatEnd(string fileName, int tableNum, int rowNum, int rowCount)
39         {
40             using (var document = DocX.Load(fileName))
41             {
42                 var table = document.Tables[tableNum];
43                 for (int i = 0; i < rowCount; i++)
44                 {
45                     var row = table.Rows.AsEnumerable().Last();
46                     table.InsertRow(row, rowNum, true);
47                     rowNum++;
48                 }
49                 document.Save();
50             }
51         }
View Code

在使用Microsoft.Office.Interop.Word进行新增列Row的时候就抛Com组件错误,所以就使用了Docx。成功解决了问题

提供一个具体的例子-Utilitys.zip

欢迎留言:相互讨论,相互学习。