文档章节

高效读取Excel

魂祭心
 魂祭心
发布于 2017/07/21 18:12
字数 511
阅读 31
收藏 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
博文 49
码字总数 78163
作品 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
Excel 十大学习体系-表哥、表姐、表神之路必会(含47门实战课程推荐)

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

51CTO学院
2017/10/25
0
0
微信记录恢复助手官方版

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

相心的泪
2016/08/23
5
0
Crab2Died/Excel4J

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

Crab2Died
2017/06/11
0
0

没有更多内容

加载失败,请刷新页面

加载更多

xilinx资源

本系列教学视频由赛灵思高级战略应用工程师带领你:从零开始,一步步深入 掌握 HLS 以及 UltraFAST 设计方法,帮助您成为系统设计和算法加速的大拿! http://www.eetrend.com/topics/2018-0...

whoisliang
22分钟前
0
0
=====BJmeter性能测试小接=====

一、性能测试分类 1、负载测试: 通过逐步加压的方法,达到既定的性能阈值的目标,阈值的设定应是小于某个值,如cpu使用率小于等于80% 2、压力测试: 通过逐步加压的方法,使得系统的某些资源...

覃光林
26分钟前
1
0
企业级开源四层负载均衡解决方案--LVS

网盘链接 企业级开源四层负载均衡解决方案--LVS 本课程将在Linux环境下,学习配置使用LVS,对Web集群和MySQL集群进行负载均衡,并结合利用Keepalived实现负载均衡器的高可用,实现对后端Rea...

qq__2304636824
31分钟前
2
0
Windows上安装Spacemacs

emacs安装 下载地址emacs 安装比较简单,解压后执行\bin\addpm.exe即可 emacs配置 emacs的默认配置文件路径和.emacs.d文件夹都是在Windows主目录下的 C:\Users\Administrator\AppData\Roami...

yxmsw2007
47分钟前
0
0
OSChina 周一乱弹 —— 鱼生不值得

Osc乱弹歌单(2018)请戳(这里) 【今日歌曲】 @瘟神灬念:分享新裤子的单曲《没有理想的人不伤心 (Remix版)》: 《没有理想的人不伤心 (Remix版)》- 新裤子 手机党少年们想听歌,请使劲儿戳...

小小编辑
今天
215
9

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部