文档章节

高效读取Excel

魂祭心
 魂祭心
发布于 2017/07/21 18:12
字数 511
阅读 39
收藏 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
浦东
后端工程师
私信 提问
Python利用pandas处理Excel数据的应用

Python利用pandas处理Excel数据的应用 最近迷上了高效处理数据的pandas,其实这个是用来做数据分析的,如果你是做大数据分析和测试的,那么这个是非常的有用的!!但是其实我们平时在做自动化...

上官夏洛特
2018/11/20
0
0
[不懂就问]Web页面批量读取Excel数据后提交到数据库 批量读取是放在后端用Java处理还是放到前端用js处理?那种更稳定更高效

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

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

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

BrainZou
2018/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

没有更多内容

加载失败,请刷新页面

加载更多

OSChina 周三乱弹 —— 孤独到都和病毒发生了感情了

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @-冰冰棒- :#今日歌曲推荐# 逃跑计划《一万次悲伤 (Live)》 《一万次悲伤 (Live)》- 逃跑计划 手机党少年们想听歌,请使劲儿戳(这里) 现在...

小小编辑
26分钟前
6
2
test

//// main.c// Test//// Created by 吕颖 on 2019/1/16.// Copyright © 2019年 carmen. All rights reserved.//#include <stdio.h>#include <stdlib.h>#include <t......

carmen-ly
今天
1
0
Android webview热门组件agentweb:4.0.2无法自适应的问题

Android webview热门组件agentweb:4.0.2无法自适应的问题 //设置自适应屏幕,两者合用mAgentWeb.getAgentWebSettings().getWebSettings().setUseWideViewPort(true); //将图片调整到适合w...

Gemini-Lin
今天
5
0
如何维护一个自己的 golang doc 服务

本文内容是如何维护一个golang 在线的doc 服务。 1 什么是godoc ? godoc 是 golang 官方提供的文档生成工具, 2 为什么要有godoc ? 我们经常遇到一个问题,就是代码和文档不一致,线上代码版...

鼎铭
今天
5
0
js中的对象创建的模式以及继承模式

对象创建模式: 工厂模式 构造函数模式 原型模式 继承模式 原型式继承 寄生式继承 构造函数 原型式和构造函数的组合式(缺点:运行两次超类类函数,积累函数的属性被挂载在原型对象上和实例对...

莫西摩西
昨天
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部