文档章节

高效读取Excel

魂祭心
 魂祭心
发布于 2017/07/21 18:12
字数 511
阅读 35
收藏 1

原理 直接解析excel源文件,仅仅读取关心的数据,样式,公式,合并等等统统丢弃。

public class Option
{
    /// <summary>
    /// 开始行
    /// </summary>
    public int StartRow { get; set; }
    /// <summary>
    /// 结束行
    /// </summary>
    public int EndRow { get; set; }
    public Option()
    {
        StartRow = 0;
        EndRow = int.MaxValue;
    }
}
public class ExcelDataParser
{
    #region Field
    private Option option;
    #endregion

    #region Constructor
    public ExcelDataParser(Option option)
    {
        this.option = option;
    }
    #endregion

    #region Public Method
    /// <summary>
    /// 解析sheet数据
    /// </summary>
    /// <param name="xmlPath"></param>
    /// <returns></returns>
    public DataSet ParserSheets(string xmlPath)
    {
        DataSet ds = new DataSet();
        using (ZipArchive zip = ZipFile.OpenRead(xmlPath))
        {
            var zipEntry = zip.GetEntry(@"xl/sharedStrings.xml");
            var map = new Dictionary<int, string>();
            XmlTextReader readerXml = null;
            if (zipEntry != null)
            {
                readerXml = new XmlTextReader(zipEntry.Open());
                map = GetShareString(readerXml);
            }


            zipEntry = zip.GetEntry(@"xl/workbook.xml");
            readerXml = new XmlTextReader(zipEntry.Open());
            var sheetNames = GetSheetName(readerXml);
            foreach (var sheetName in sheetNames)
            {
                zipEntry = zip.GetEntry(@"xl/worksheets/sheet" + sheetName.Key + ".xml");
                readerXml = new XmlTextReader(zipEntry.Open());
                var table = ParserSheetData(readerXml, map);
                table.TableName = sheetName.Value;
                ds.Tables.Add(table);
            }
        }
        return ds;
    }
    #endregion

    #region Private Method
    /// <summary>
    /// 解析数据
    /// </summary>
    /// <param name="readerXml"></param>
    /// <param name="strMap"></param>
    /// <returns></returns>
    DataTable ParserSheetData(XmlTextReader readerXml, Dictionary<int, string> strMap)
    {
        DataTable dt = new DataTable();
        int row = -1;
        int column = 0;
        DataRow dataRow = null;
        while (readerXml.Read())
        {
            if (row > option.EndRow) break;
            if (readerXml.NodeType == XmlNodeType.Element)
            {
                if (readerXml.Name == "row")
                {
                    row++;
                    column = 0;
                    if (dt.Columns.Count > 0)
                    {
                        dataRow = dt.NewRow();
                        dt.Rows.Add(dataRow);
                        for (; row <= option.StartRow; row++)
                        {
                            readerXml.ReadToNextSibling("row");
                        }
                    }
                }
                else if (readerXml.Name == "v")
                {
                    string data = "";
                    if (string.IsNullOrEmpty(readerXml.GetAttribute("t")))
                    {
                        data = readerXml.ReadInnerXml();
                    }
                    else
                    {
                        var strIndex = int.Parse(readerXml.ReadInnerXml());
                        data = strMap.ContainsKey(strIndex) ? strMap[strIndex] : strIndex.ToString();
                    }

                    if (row == 0)
                    {
                        dt.Columns.Add(new DataColumn(data));
                    }
                    else
                    {
                        dataRow[column] = data;
                    }
                    column++;
                }
                else if (readerXml.Name == "t")
                {//直接取值
                    var data = readerXml.ReadInnerXml();
                    if (row == 0)
                    {
                        dt.Columns.Add(new DataColumn(data));
                    }
                    else
                    {
                        dataRow[column] = data;
                    }
                    column++;
                }
            }
        }
        return dt;
    }

    /// <summary>
    /// 字符串映射的map
    /// </summary>
    /// <param name="readerXml"></param>
    /// <returns></returns>
    Dictionary<int, string> GetShareString(XmlTextReader readerXml)
    {
        var index = 0;
        Dictionary<int, string> strMap = new Dictionary<int, string>();
        while (readerXml.Read())
        {
            if (readerXml.NodeType == XmlNodeType.Element)
            {
                if (readerXml.Name == "t")
                {
                    strMap.Add(index, readerXml.ReadInnerXml());
                    index++;
                }
            }
        }
        return strMap;
    }

    /// <summary>
    /// 获取sheet序号和名称的映射
    /// </summary>
    /// <param name="readerXml"></param>
    /// <returns></returns>
    Dictionary<int, string> GetSheetName(XmlTextReader readerXml)
    {
        Dictionary<int, string> sheetMap = new Dictionary<int, string>();
        while (readerXml.Read())
        {
            if (readerXml.NodeType == XmlNodeType.Element)
            {
                if (readerXml.Name == "sheet")
                {
                    var id = readerXml.GetAttribute("sheetId");
                    var name = readerXml.GetAttribute("name");
                    sheetMap.Add(int.Parse(id), name);
                }
            }
        }
        return sheetMap;
    }

    #endregion
}

测试结果 excel规模:100w*24 读取进DataTable 测试结果:时间约1分半,内存峰值1.6g

输入图片说明

© 著作权归作者所有

共有 人打赏支持
魂祭心
粉丝 12
博文 51
码字总数 84650
作品 0
浦东
后端工程师
私信 提问
[不懂就问]Web页面批量读取Excel数据后提交到数据库 批量读取是放在后端用Java处理还是放到前端用js处理?那种更稳定更高效

Web页面批量读取Excel数据后提交到数据库 批量读取是放在后端用Java处理还是放到前端用js处理?那种更稳定更高效

尼禄花嫁
10/23
0
0
利用Python进行数据分析(九)

二进制数据格式 pickle序列化 实现二进制存储最简单方法就是使用pickle序列化。 pandas可以用把frame以pickle形式保存到磁盘上的方法。读取使用的是。 使用HDF5格式 HDF指层次型数据格式(hi...

BrainZou
01/07
0
0
Apache POI读取和创建Excel ----01(简单操作)

public class ExcelCreatAndRead { / 使用Apache POI创建Excel文档 */ public static void createXL(){ /Excel文件要存放的位置,假定在D盘下/ String outputFile="D:\test.xlsx"; try { //创......

小白菜鸟1
2017/11/16
0
0
微信记录恢复助手官方版

详细介绍微信记录恢复助手自带微信记录导出功能,可以帮助苹果手机用户随时提取和恢复iPhone中的微信记录软件功能:内容读取有木有为了查找某句话翻手机翻到手软,有木有感觉在4英寸的屏幕上...

相心的泪
2016/08/23
5
0
Excel 十大学习体系-表哥、表姐、表神之路必会(含47门实战课程推荐)

身在职场,无论你身处什么职业,办公室白领?财务?项目经理?互联网运营?销售?市场?行政?HR?...... Office办公软件几乎是考察个人能力的标配。Excel表格的使用也是衡量工作中不可忽视的...

51CTO学院
2017/10/25
0
0

没有更多内容

加载失败,请刷新页面

加载更多

阿里云ACM:云原生配置管理利器

摘要: 在传统架构中,如果配置信息有变更,通常是登陆服务器手动修改配置来使配置生效。在微服务架构中,应用数和节点数由于微服务化数量激增,导致发布次数增加,配置变更难度加大,通常是...

阿里云官方博客
12分钟前
1
0
js 对象合并

var o1 = { a: 1 };var o2 = { b: 2 };var o3 = { c: 3 };var obj = Object.assign(o1, o2, o3);console.log(obj); // { a: 1, b: 2, c: 3 }console.log(o1); // { a: 1, b: 2, c: 3 ......

zdglf
12分钟前
0
0
iframe引入方法

在js里定义: $(function () { $(".frameHead").load("../common/header.html"); $(".frameFoot").load("../common/footer.html"); }) 在需要导入iframe的页面添加标签<div class="frameHead......

kitty1116
12分钟前
0
0
华尔街留下的指标之王(附代码展示)

一. 写在前面的话 有人认为价格围绕价值上下波动,研究投资标的内在价值,于是就出现了基本面派; 有人为价格反映了一切,所有的信息(包括基本面)都反映到了盘面价格中,于是就有了技术面派...

酒逢知己千杯少
16分钟前
0
0
基于算法的建模--小结

中国龙-扬科
23分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部