VSTO学习笔记(七)基于WPF的Excel分析、转换小程序

原文:VSTO学习笔记(七)基于WPF的Excel分析、转换小程序

近期因为工作的需要,要批量处理Excel文件,于是写了一个小程序,来提升工作效率。

小程序的功能是对Excel进行一些分析、验证,然后进行转换。

 

  1. 概述
  1. 小程序主界面如下:

首先选择一个日期和类别,从命名上对待分析的Excel文件进行过滤。点击【浏览】选择待分析的Excel文件所在的目录,

程序中会获取所有子目录。然后点击【执行分析】就会按照左边CheckBox中的选择进行分析,分析结果显示在每一行中间。【修改配置】可以对分析规则进行设置,此处还未完善,后续再改进。分析结束后点击【执行转换】可以将Exce转换为我们需要的格式和内容,去除只读、重命名、转换格式、去除保护、去除公式、显示零设置等。

 

  1. 主要对Excel做如下几种分析:

只读分析:判断Excel的文件属性是否为只读;

命名分析:判断Excel的文件名是否符合既定规范,包含的工作表是否在有效值列表中;

格式分析:判断Excel的格式是否符合既定规范(是哪一种Excel,2003?2007?)

保护分析:判断Excel是否包含工作簿保护、工作表保护;

公式分析:判断Excel的单元格中是否包含公式;

显示零分析:判断Excel中的工作表是否设置为零值显示。

 

前五种都比较好理解,只有最后一种"显示零分析"需要介绍一下。

"显示零"是指什么呢?在Excel中,若单元格中包含的数值为0,则可以通过设置来决定0值是否显示,这种设置在某些情况下是有意义的。以Excel 2010为例,我们来看一下怎么设置"零值显示" :

2.1、随便打开一个Excel 2010文件,点击【File】 -->【Options】:

 

2.2、在【Advanced】选项卡中,找到【Display options for this worksheet】,选中或取消【Show a zero in cells that have zero value】,点击【OK】即可:

注意这种设置是工作表级别的,即当前设置只对所选择工作表有效。为什么要单独做这种分析呢?若一个工作表中有大量的区域都包含零值,此时若设置为零值显示则会使得工作表的内容非常杂乱,影响美观;其他情况下我们设置为零值显示,这样方便程序处理,即读取或写入单元格中的数值。

 

  1. 分析完成后会显示出分析结果,并可以【查看明细】按钮来查看具体的内容,可以精确到单元格,如XX单元格包含公式,公式是什么;XX工作表包含保护等。其中公式的分析结果会记录日志,方便查看。

 

  1. 程序中有一个全局配置文件GolbalConfig.xml,来存储分析规则,其他的一些配置信息等:

 

  1. 代码

    <?xml version="1.0" encoding="utf-8" ?>
    <ExcelValidate>
        <SelectedDate></SelectedDate>
        <ReportKind>
            <Report name="不限"></Report>
            <Report name="储备"></Report>
            <Report name="吨煤"></Report>
            <Report name="汇总"></Report>
        </ReportKind>
        <ReportNames>
            <ReportName IsSum="true" reg="^\d{1,2}月汇总表.xlsx?$">
                <SheetNames>
                    <SheetName name="累计库存"></SheetName>
                    <SheetName name="累计消耗"></SheetName>
                    <SheetName name="原煤1 "></SheetName>
                    <SheetName name="各业务科平均库存储备资金统计 "></SheetName>
                    <SheetName name="各业务科库存储备资金统计"></SheetName>
                    <SheetName name="累计库存资金统计报表"></SheetName>
                    <SheetName name="累计消耗资金统计报表"></SheetName>
                    <SheetName name="本月库存资金统计报表"></SheetName>
                    <SheetName name="本月消耗资金统计报表"></SheetName>
                    <SheetName name="库存储备资金完成情况统计表"></SheetName>
                    <SheetName name="各单位平均库存储备资金统计表"></SheetName>
                    <SheetName name="各单位吨煤材料费"></SheetName>
                    <SheetName name="各业务科吨煤材料费"></SheetName>
                    <SheetName name="产量进尺表"></SheetName>
                    <SheetName name="全局1表"></SheetName>
                    <SheetName name="煤业1表"></SheetName>
                    <SheetName name="全局2表"></SheetName>
                    <SheetName name="煤业2表"></SheetName>
                    <SheetName name="袁庄矿1表"></SheetName>
                    <SheetName name="朱庄矿1表"></SheetName>
                    <SheetName name="杨庄矿1表"></SheetName>
                    <SheetName name="芦岭矿1表"></SheetName>
                    <SheetName name="朱仙庄1表"></SheetName>
                    <SheetName name="童亭矿1表"></SheetName>
                    <SheetName name="桃园矿1表"></SheetName>
                    <SheetName name="祁南矿1表"></SheetName>
                    <SheetName name="许疃矿1表"></SheetName>
                    <SheetName name="涡北矿1表"></SheetName>
                    <SheetName name="孙疃矿1表"></SheetName>
                    <SheetName name="淮选厂1表"></SheetName>
                    <SheetName name="临选厂1表"></SheetName>
                    <SheetName name="铁运处1表"></SheetName>
                    <SheetName name="工程处1表"></SheetName>
                    <SheetName name="总仓库1表"></SheetName>
                    <SheetName name="岱河矿1表"></SheetName>
                    <SheetName name="朔里矿1表"></SheetName>
                    <SheetName name="石台矿1表"></SheetName>
                    <SheetName name="临涣矿1表"></SheetName>
                    <SheetName name="海孜矿1表"></SheetName>
                    <SheetName name="刘店矿1表"></SheetName>
                    <SheetName name="袁庄矿2表"></SheetName>
                    <SheetName name="朱庄矿2表"></SheetName>
                    <SheetName name="杨庄矿2表"></SheetName>
                    <SheetName name="芦岭矿2表"></SheetName>
                    <SheetName name="朱仙庄2表"></SheetName>
                    <SheetName name="童亭矿2表"></SheetName>
                    <SheetName name="桃园矿2表"></SheetName>
                    <SheetName name="祁南矿2表"></SheetName>
                    <SheetName name="许疃矿2表"></SheetName>
                    <SheetName name="涡北矿2表"></SheetName>
                    <SheetName name="孙疃矿2表"></SheetName>
                    <SheetName name="岱河矿2表"></SheetName>
                    <SheetName name="朔里矿2表"></SheetName>
                    <SheetName name="石台矿2表"></SheetName>
                    <SheetName name="临涣矿2表"></SheetName>
                    <SheetName name="海孜矿2表"></SheetName>
                    <SheetName name="刘店矿2表"></SheetName>
                </SheetNames>
            </ReportName>
            <ReportName IsSum="false" reg="^\d{2}\w{3}(储备|吨煤)报表.xlsx?$">
                <SheetNames>
                    <SheetName reg="^\d{4}.\d{2}$"></SheetName>
                </SheetNames>
            </ReportName>
        </ReportNames>
        <MineNames>
            <MineName name="岱河矿"></MineName>
            <MineName name="工程处"></MineName>
            <MineName name="海孜矿"></MineName>
            <MineName name="淮选厂"></MineName>
            <MineName name="临涣矿"></MineName>
            <MineName name="临选厂"></MineName>
            <MineName name="刘店矿"></MineName>
            <MineName name="芦岭矿"></MineName>
            <MineName name="祁南矿"></MineName>
            <MineName name="石台矿"></MineName>
            <MineName name="朔里矿"></MineName>
            <MineName name="孙疃矿"></MineName>
            <MineName name="桃园矿"></MineName>
            <MineName name="铁运处"></MineName>
            <MineName name="童亭矿"></MineName>
            <MineName name="涡北矿"></MineName>
            <MineName name="许疃矿"></MineName>
            <MineName name="杨庄矿"></MineName>
            <MineName name="袁庄矿"></MineName>
            <MineName name="朱仙庄"></MineName>
            <MineName name="朱庄矿"></MineName>
            <MineName name="总仓库"></MineName>
        </MineNames>
    </ExcelValidate>

     

    分析细则

  1. 只读分析:用File.IsReadOnly判断即可;
  2. 命名分析:基于GolbalConfig.xml中的配置进行分析,主要是正则表达式和有效值列表;
  3. 格式分析:也是用正则表达式进行分析

 

Regex excel = new Regex(@"^.xlsx?$");

 

 

  1. 保护分析:我们知道Excel中的保护功能分为两种级别,一种是工作簿保护,一种是工作表保护,这里要区分对待。

在Excel COM API 中,工作簿保护用Workbook. ProtectWindows和Workbook. ProtectStructure进行判断,这两种保护有什么区别呢?还是以Excel 2010为例,在【Preview】选项卡中点击【Protect Workbook】:

可以看到Structure默认被选中:

 

我们保持选中Structure不变,输入密码、确认密码后保存,看看效果:

此时可以改变工作表窗口的大小,但是不能添加、删除、重命名、复制工作表等,右键中相应选项不可用:

另一种Windows保护恰好相反。

工作表保护可以对行、列、单元格、区域等做更细粒度的控制:

 

  1. 公式分析:用Excel COM API中的Range.HasFormula来判断;
  2. 显示零分析:这个比较特殊,我在Excel COM API中没有找到编程设置的方法,无奈使用OpenXML SDK 2.0中的方法进行验证。从Office 2007开始,Word、Excel、PowerPoint全面使用OpenXML作为存储格式,微软也相应提供了OpenXML SDK,方便开发人员处理OpenXML文档,关于OpenXML SDK的介绍,请参阅我的另一篇博文:

OpenXML SDK 2.0悄然发布

OpenXML SDK是个很好的东西,但是网上资源太少,OpenXML的架构也非常复杂,看着帮助文档中数量庞大的类有些茫然,关于OpenXML SDK我研究也不多,感兴趣的朋友可以一起讨论。

首先需要下载OpenXML SDK 2.0(可以在这里下载),其中有一个工具:OpenXML SDK 2.0 Productivity Tool,功能非常强大,可以查看OpenXML 文档的架构,比较两个OpenXML 文档架构的不同,甚至可以将OpenXML 文档反编译为C#代码。

下面我们来看一下显示零的设置在OpenXML架构中是如何显示的。Excel 中默认是显示零值的,先参照2.1、2.2中的步骤设置为零值不显示,然后打开OpenXML SDK 2.0 Productivity Tool:

 

点击【Open File】找到刚才设置为零值不显示的Excel文件,点击【Reflector Code】:

 

Ctrl + F,输入:ShowZeros查找,可以看到在SheetView类的属性里:

 

下面用OpenXML SDK 2.0中的方法进行分析:

 

代码

                        using (SpreadsheetDocument mySpreadsheet = SpreadsheetDocument.Open(file.FullName, false))
                        {
                            var book = mySpreadsheet.WorkbookPart.Workbook;
                            foreach (WorksheetPart s in book.WorkbookPart.WorksheetParts)
                            {
                                foreach (SheetView view in s.Worksheet.SheetViews)
                                {
                                    if (view.ShowZeros != null)
                                    {
                                        if (!view.ShowZeros)
                                        {
                                            this.__int显示零单元格个数++;
                                            this.__dic显示零.Add(this.__int显示零单元格个数, file.FullName);
                                        }
                                    }
                                }
                            }
                        }

 

执行转换
 

分析结束后,就可以执行转换了,来达到我们需要的格式、命名等要求。转换前默认备份,防止转换错误造成数据丢失,

将待分析的Excel所在的目录整个复制到指定位置。备份目录名取当前时间的年月日时分秒。

这里我引用了Microsoft.VisualBasic.dll进行复制目录操作,否则需要写一个递归函数,C#本身未提供复制目录的方法:

 

取消保护时需要输入工作簿密码、工作表密码:

 

  1. 运行效果

 

  1. 小结

本次用一个小程序的方式对Excel常见的方面进行了分析与验证,可以避免繁琐的手工处理。程序全部使用了WPF设计,主要运用了Excel COM API来对Excel进行操作,掺杂有少量的Linq to XML。程序中大量使用了foreach循环,效率有待提高,尤其是公式判断时会比较慢,你可以根据需要自行修改代码。仅供测试,在生产环境中情谨慎使用。

时间: 2024-08-31 19:45:30

VSTO学习笔记(七)基于WPF的Excel分析、转换小程序的相关文章

VSTO学习笔记(十四)Excel数据透视表与PowerPivot

原文:VSTO学习笔记(十四)Excel数据透视表与PowerPivot 近期公司内部在做一种通用查询报表,方便人力资源分析.统计数据.由于之前公司系统中有一个类似的查询使用Excel数据透视表完成的,故我也打算借鉴一下. 测试代码下载    原有系统是使用VBA编写的,难以维护,且对新的操作系统如Windows 7.64位架构不支持,我准备用VSTO进行重写. 数据透视表是一种交互式的表,可以进行某些计算,如求和与计数等.所进行的计算与数据跟数据透视表中的排列有关. 数据透视表是一种完全自助式

VSTO学习笔记(二)Excel对象模型

原文:VSTO学习笔记(二)Excel对象模型 上一次主要学习了VSTO的发展历史及其历代版本的新特性,概述了VSTO对开发人员的帮助和效率提升.从这次开始,将从VSTO 4.0开始,逐一探讨VSTO开发中方方面面,本人接触VSTO时间不长,也是一次尝试.鉴于Excel在整个Office家族中的重要地位,故先从Excel开始介绍,后续内容会陆续介绍Word.PowerPoint.Outlook.InfoPath等.由于VSTO 4.0建立在Office 2010基础之上,先介绍一下Office

VSTO学习笔记(九)浅谈Excel内容比较

原文:VSTO学习笔记(九)浅谈Excel内容比较 说起文件内容比较,或许我们首先想到的是UltraCompare这类专业比较的软件,其功能非常强大,能够对基于文本的文件内容作出快速.准确的比较,有详细的差异报告,非常便于分析.其实,各种版本控制软件中也包含有或多或少的比较功能,如TFS.CVS.SVN等.但是如果待比较的文件不是基于文本类型的,那就无能为力了.今天我就来谈一谈Excel的比较方法及其特点,也和大家共同探讨一下,如果你有更好的方法,欢迎分享.   一.Excel的文件架构 Exc

VSTO学习笔记(五)批量编辑Excel 2010 x64

原文:VSTO学习笔记(五)批量编辑Excel 2010 x64 近期因为工作的需要,经常要批量处理大量的Excel文件,如果纯手工一个个修改,非常的麻烦,于是写了这么一个帮助类,希望能对你有所帮助.里面很多方法可以进一步推广,增减适当的参数,部分方法用到了C# 4.0新特性,如果需要调试,请安装Visual Studio 2010. 示例代码下载 本系列所有示例代码均在 Visual Studio 2010 Ultimate RC + Office 2010 Professional Plus

VSTO学习笔记(一)VSTO概述

原文:VSTO学习笔记(一)VSTO概述 接触VSTO纯属偶然,前段时间因为忙于一个项目,在客户端Excel中制作一个插件,从远程服务器端(SharePoint Excel Services)上下载Excel到本地打开,用户编辑后再上传回服务器端.当时工期紧迫,临时查了些资料,用VSTO + Excel COM API完成.正因为这个项目,我发现了VSTO的强大功能与潜力,决定抽出一些时间来好好研究下. 示例代码下载 本系列所有示例代码均在 Visual Studio 2010 Beta 2 +

VSTO 学习笔记(十三)谈谈VSTO项目的部署

原文:VSTO 学习笔记(十三)谈谈VSTO项目的部署 一般客户计算机专业水平不高,但是有一些Office水平相当了得,尤其对Excel的操作非常熟练.因此如果能将产品的一些功能集成在Office中,将会有很好的基础. 但是由于客户安装的Office版本不一,所以VSTO项目的部署问题显得尤为重要,需要考虑很多问题. 测试代码下载 本系列所有测试代码均在Visual Studio 2010 Ultimate SP1 + Office 2010 Professional Plus x64 SP1

VSTO 学习笔记(十)Office 2010 Ribbon开发

原文:VSTO 学习笔记(十)Office 2010 Ribbon开发 微软的Office系列办公套件从Office 2007开始首次引入了Ribbon导航菜单模式,其将一系列相关的功能集成在一个个Ribbon中,便于集中管理.操作.这种Ribbon是高度可定制的,用户可以将自己常用的功能进行单独设置,提高工作效率.但是由于Office 2003时代用户的操作习惯已经养成,结果到了Office 2007很多菜单.按钮都找不到了,着实有些尴尬.经过一段时间的适应,相信大多数用户已经习惯Ribbon

VSTO学习笔记(三) 开发Office 2010 64位COM加载项

原文:VSTO学习笔记(三) 开发Office 2010 64位COM加载项 一.加载项简介 Office提供了多种用于扩展Office应用程序功能的模式,常见的有: 1.Office 自动化程序(Automation Executables) 2.Office加载项(COM or Excel Add-In) 3.Office文档代码或模板(Code Behind an Office Document or Template) 4.Office 智能标签(Smart Tags) 本次我们将学习使

VSTO学习笔记(四)从SharePoint 2010中下载文件

原文:VSTO学习笔记(四)从SharePoint 2010中下载文件 上一次我们开发了一个简单的64位COM加载项,虽然功能很简单,但是包括了开发一个64位COM加载项的大部分过程.本次我们来给COM加载项添加一些功能:从SharePoint 2010的文档库中下载一个Excel文档到本地. 示例代码下载 本系列所有示例代码均在 Visual Studio 2010 Ultimate RC + Office 2010 Professional Plus Beta x64 上测试通过.   1.