文档章节

高效读取Excel

魂祭心
 魂祭心
发布于 2017/07/21 18:12
字数 511
阅读 28
收藏 1
点赞 0
评论 0

原理 直接解析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

输入图片说明

© 著作权归作者所有

共有 人打赏支持
魂祭心
粉丝 6
博文 48
码字总数 70991
作品 0
浦东
后端工程师
利用Python进行数据分析(九)

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

BrainZou ⋅ 01/07 ⋅ 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

微信记录恢复助手官方版

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

相心的泪 ⋅ 2016/08/23 ⋅ 0

Excel 十大学习体系-表哥、表姐、表神之路必会(含47门实战课程推荐)

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

51CTO学院 ⋅ 2017/10/25 ⋅ 0

Crab2Died/Excel4J

Excel4J v2.x 一. v2.x新特性 Excel读取支持部分类型转换了(如转为Integer,Long,Date(部分)等) v2.0.0之前只能全部内容转为String Excel支持非注解读取Excel内容了,内容存于对象内 现在支持导...

Crab2Died ⋅ 2017/06/11 ⋅ 0

使用java读取Excel表格中的数据 ,解决方案搜集

Java EXCEL API简介 Java Excel是一开放源码项目,通过它Java开发人员可以读取Excel文件的内容、创建新的Excel文件、更新已经存在的Excel文件。使用该API非Windows操作系统也可以通过纯Java应...

不最醉不龟归 ⋅ 2016/11/01 ⋅ 0

Excel2db-excel转成二进制文件

目的: 游戏开放中有原型数据,而原型数据经常都是通过excel进行编写,关于程序如何去读取excel中的数据,方法有很多种,比如: 1.将excel导入mysql中,然后由程序去读取数据库,但是客户端无法...

ksfzhaohui ⋅ 2015/09/08 ⋅ 0

Python读写与追加excel文件实例讲解

读写与追加excel文件用的是 xlwt(写),xlrd(读),xlutils(操作excel)这三个包 三个模块的安装读取excel文件(.xls .xlsx)写入excel文件追加excel文件 1.三个模块的安装 pip install ...

呆萌的代Ma ⋅ 2017/12/21 ⋅ 0

excel 转换和解析 ndb 文件工具--excel2db

目的: 游戏开放中有原型数据,而原型数据经常都是通过excel进行编写,关于程序如何去读取excel中的数据,方法有很多种,比如: 1.将excel导入mysql中,然后由程序去读取数据库,但是客户端无法...

ksfzhaohui ⋅ 2016/11/28 ⋅ 1

ksfzhaohui/excel2db

Excel转二进制工具 目的: 游戏开放中有原型数据,而原型数据经常都是通过excel进行编写,关于程序如何去读取excel中的数据,方法有很多种,比如: 1.将excel导入mysql中,然后由程序去读取数...

ksfzhaohui ⋅ 2016/11/28 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

java软件工程师简历中项目经验怎么写?

作者:暗灭 链接:https://www.zhihu.com/question/20695310/answer/180691302 来源:知乎 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 直接给你贴个我自己的简历...

颖伙虫 ⋅ 28分钟前 ⋅ 0

Confluence 6 恢复一个站点有关使用站点导出为备份的说明

推荐使用生产备份策略。我们推荐你针对你的生产环境中使用的 Confluence 参考 Production Backup Strategy 页面中的内容进行备份和恢复(这个需要你备份你的数据库和 home 目录)。XML 导出备...

honeymose ⋅ 今天 ⋅ 0

JavaScript零基础入门——(九)JavaScript的函数

JavaScript零基础入门——(九)JavaScript的函数 欢迎回到我们的JavaScript零基础入门,上一节课我们了解了有关JS中数组的相关知识点,不知道大家有没有自己去敲一敲,消化一下?这一节课,...

JandenMa ⋅ 今天 ⋅ 0

火狐浏览器各版本下载及插件httprequest

各版本下载地址:http://ftp.mozilla.org/pub/mozilla.org//firefox/releases/ httprequest插件截至57版本可用

xiaoge2016 ⋅ 今天 ⋅ 0

Docker系列教程28-实战:使用Docker Compose运行ELK

原文:http://www.itmuch.com/docker/28-docker-compose-in-action-elk/,转载请说明出处。 ElasticSearch【存储】 Logtash【日志聚合器】 Kibana【界面】 答案: version: '2'services: ...

周立_ITMuch ⋅ 今天 ⋅ 0

使用快嘉sdkg极速搭建接口模拟系统

在具体项目研发过程中,一旦前后端双方约定好接口,前端和app同事就会希望后台同事可以尽快提供可供对接的接口方便调试,而对后台同事来说定好接口还仅是个开始、设计流程,实现业务逻辑,编...

fastjrun ⋅ 今天 ⋅ 0

PXE/KickStart 无人值守安装

导言 作为中小公司的运维,经常会遇到一些机械式的重复工作,例如:有时公司同时上线几十甚至上百台服务器,而且需要我们在短时间内完成系统安装。 常规的办法有什么? 光盘安装系统 ===> 一...

kangvcar ⋅ 昨天 ⋅ 0

使用Puppeteer撸一个爬虫

Puppeteer是什么 puppeteer是谷歌chrome团队官方开发的一个无界面(Headless)chrome工具。Chrome Headless将成为web应用自动化测试的行业标杆。所以我们很有必要来了解一下它。所谓的无头浏...

小草先森 ⋅ 昨天 ⋅ 0

Java Done Right

* 表示难度较大或理论性较强。 ** 表示难度更大或理论性更强。 【Java语言本身】 基础语法,面向对象,顺序编程,并发编程,网络编程,泛型,注解,lambda(Java8),module(Java9),var(...

风华神使 ⋅ 昨天 ⋅ 0

Linux系统日志

linux 系统日志 /var/log/messages /etc/logrotate.conf 日志切割配置文件 https://my.oschina.net/u/2000675/blog/908189 logrotate 使用详解 dmesg 命令 /var/log/dmesg 日志 last命令,调......

Linux学习笔记 ⋅ 昨天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部