`
xiaozhi7616
  • 浏览: 195902 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

VBA制作Excel报表

阅读更多

项目中使用Excel生成报表相信很多人都使用过,现在各种各样的专门实现报表的工具包也越来越多,很多基于Flash实现的都非常漂亮。Excel 报表与其相比自然是有优点也有缺点,缺点是样式不够美观(大多数人还是停留在Office 2003阶段),数据量大的时候表现不清晰,太多的sheet会让人很难找到目标,优点是Excel可以更加灵活的展示数据之间的结构,和揭示深层次的数据间的关系, 为统计分析很好的提供服务。 究竟选择什么样的报表工具关键还是看用户需求,选择最适合的才是正确的。

 

如题,VBA制作Excel报表和Java没有关系,内置VBA的Excel好像Java是不能直接生成的,我项目中需求是这样:在服务器端对原始数据进行条件计算,然后生成数据并展现到Web端,再拷贝这些数据到Excel里面作为源数据,通过VBA生成各种各样的报表。(这种方式实在是感觉不好,如果有朋友有更好的方法,望不吝赐教,谢谢)

 

下面介绍一下在项目中使用的过程,以及如何使用VBA制作报表,数据是一些简单的模拟数据,在生成的报表中多为数据透视表和数据透视图。

 

数据透视表参考:

 

现在开始动手了,拷贝源数据到Excel中,我从Office Online中找了一个Pivot table(数据透视表)的例子来做演示(代码在附件中),源数据中含有以下5个字段:

  1. 国家
  2. 销售人员名称
  3. 订单日期
  4. 订单号
  5. 订单金额



 

 

Excel技巧

  • 冻结窗口:从上图可以看到不论我们滚动到第几行,第一行标题总是固定停留在那里的,只需要将光标放到A2单元格,点击 window - Freeze Panes,冻结窗口的效果就可以实现了,如果要撤销的话,还是点击 window - Unfreeze Panes 就可以了。

注意

  1. 源数据必须具有特定的业务含义,并且粒度要细,因为之后所产生的报表都是基于这些源数据的,源数据的准确性是一定要保证的,如果源数据不准确,后面所生成的报表也就不能真实的反映实际情况。
  2. 个人认为还有一点要注意的就是因为源数据是在服务端生成的,如果需要进行计算,那么最好是在服务器端处理好,这样可以减轻Excel处理数据的压力。

 

 有了源数据,接下来就要对源数据进行一些处理,以便得到我们想要的结果。这时就该VBA出马了,首先要打开Excel的代码编辑窗口,通常有两种方式

  1. 使用快捷键 Alt+F11
  2. 右击 sheet 的标题栏,选择 “View Code”,如图所示
     
     

 这样就可以看到VBA的代码编辑窗口了



 

 编辑器的每一个部分的作用和操作细节就不一一介绍了,用到哪儿说到哪儿吧。

 

有了源数据,该以怎样的数据结构来操作这些源数据呢,我是搞Java的,当然第一想法就是面向对象了,最好能封装一个源数据的对象出来,这样我们要用什么直接从对象中取出来就好了,可是很不幸,VB这门语言是不支持面向对象的,那就只好假装一下了,用OO的思想来吧(我对VB不太了解,要是有什么不对的地方,希望朋友能帮忙提出来)。

 

新建一个类模块,在我们的工程VBAProject 上右击 Insert - Class Module



 
 

选中新建的类模块,可以在下面的 Properties 工具栏中修改它的 Name 属性,改为 dataObj。 



 
 

 好了,现在在右边的代码区域来把它的属性放到这个新建的类模块中,属性就是源数据中的列名,每一行数据都可以封装成一个dataObj对象,这样我们在用的时候就可以方便的取出来用了。

Public country As String
Public salePerson As String
Public orderDate As String
Public orderID As String
Public orderAmount As Double

 

 

接下来,我们新建一个模块,在 VBAProject 上新建模块,命名 “getData”,



  

 

在这个模块中建立一个 getRowData 方法来把源数据中每一行数据都封装成一个 dataObj 对象

''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' 读取 Source Data 表,封装 dataObj 对象
'
'   ByRef - By Reference, 按内存地址传递参数
'   rowDataObj - 是一个数组
'
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Sub getRowData(ByRef rowDataObj() As dataObj)

    ' 声明变量用来指定行数
    Dim rowCount As Integer
    
    ' 源数据sheet中取定从 第50000行第1列 向上方向 的单元格
    ' -1 是除去 标题栏 行的数据
    rowCount = Worksheets("Source Data").Cells(50000, 1).End(xlUp).Row - 1
    
    ' 定义数组长度
    ReDim rowDataObj(rowCount)
    Dim index As Integer

    ' 遍历 SourceData 表
    For index = 1 To rowCount
        
        ' 创建数组元素为 dataObj 类型
        Set rowDataObj(index) = New dataObj
        
        ' 为 dataObj 赋值
        rowDataObj(index).country = Trim(CStr(Worksheets("Source Data").Cells(index + 1, 1)))
        rowDataObj(index).salePerson = Trim(CStr(Worksheets("Source Data").Cells(index + 1, 2)))
        rowDataObj(index).orderDate = Trim(CStr(Worksheets("Source Data").Cells(index + 1, 3)))
        rowDataObj(index).orderID = Trim(CStr(Worksheets("Source Data").Cells(index + 1, 4)))
        rowDataObj(index).orderAmount = Trim(CStr(Worksheets("Source Data").Cells(index + 1, 5)))
        
    Next index

End Sub

 

通过这个方法,Source Data sheet上的源数据就被以 dataObj 对象的形式放到  rowDataObj() 数组里面了。在使用过程中,仅有这样的一个数组用起来不是很方便的,而且效率也不高,如果要找到一个特定的对象,那么就需要遍历整个数组,这样就非常得不偿失了,这里引入 Dictionary (字典)对象。

 

Dictionary 的好处在于它里面可以存放任何类型的数据和字典对象,而且在增加数据成员、在字典中进行迭代搜索和删除数据成员操作上的速度优势也非常明显。 Dictionary是以“键值对”的形式存放数据,非常类似 HashTable 的一种数据结构(使用参考:http://www.officefans.net/cdb/viewthread.php?tid=47628&highlight,这里就不详细的解释了)。

 

由于 Dictionary 并不是VBA具体存在的部分,而是存在于Microsoft Scripting Runtime Library(SCRRUN.DLL)中的一个对象。如果要使用 Dictionary 对象,就需要首先引入相关的动态链接库,在代码编辑窗口中,点击 Tools - References,在弹出对话框中选中 Microsoft Scripting Runtime 选项,确定,这样才可以使用 Dictionary 对象。



 
 

再新建一个模块,用来封装以 国家 为键的 Dictionary对象, 命名“initDic”

Sub initCountryDic(ByRef dic As Dictionary, rowDataObj() As dataObj)

    Dim i As Integer
    Dim tempDic As Dictionary
    
    Set dic = New Dictionary
    
    ' 遍历数组
    For i = 1 To UBound(rowDataObj)
        
        ' 建立以 country 为键的 Dictionary
        If Not dic.Exists(rowDataObj(i).country) Then
            
            Set tempDic = New Dictionary
            dic.Add rowDataObj(i).country, tempDic
            
        End If
        
    Next i

End Sub

 

 

 好了,有了这样的数据结构为下面创建我们所想要的数据透视表就打好了基础,我们可以通过源数据,来创建各种各样的不同结果的分析报表了。下面就动手做一张数据透视表吧,新建一个report模块:

Sub CreateReport(ByRef rowDataObj() As dataObj)

    Dim resDic As Dictionary
    
    ' 初始化 Dictionary 对象, 键为 country
    initDic.initCountryDic resDic, rowDataObj()
    
    Dim i As Integer
    Dim tempDic As Dictionary
    
    ' 遍历给定数组
    For i = 1 To UBound(rowDataObj)
        
        ' 将键为 country 的值赋给 tempDic
        Set tempDic = resDic(rowDataObj(i).country)
        
        ' 为 tempDic 赋值
        If Not tempDic.Exists(rowDataObj(i).salePerson) Then
            
            Set tempDic = New Dictionary
            tempDic.Add "salePerson", rowDataObj(i).salePerson
            tempDic.Add "orderDate", rowDataObj(i).orderDate
            tempDic.Add "orderID", rowDataObj(i).orderID
            tempDic.Add "orderAmount", rowDataObj(i).orderAmount
        
        End If
        
    Next i
    
    '''''''''''''''''''''''''''''''''''''''''''''''''
    '创建工作表 "Order Amounts"
    '
    '   分析每个 sales 的订单总额
    '
    '''''''''''''''''''''''''''''''''''''''''''''''''
    Dim ws As Worksheet
    Dim rowCount As Integer
    Dim columnCount As Integer
    
    ' 创建工作表,如果不存在,新建一个并命名,如果存在,需要删除已存在的工作表,再新建一个,而不能简单清空这个工作表
    If Not Utils.WorksheetExists(ThisWorkbook, "Order Amounts") Then
        Set ws = Sheets.Add
        ws.Name = "Order Amounts"
    Else
        Set ws = Worksheets("Order Amounts")
        Application.DisplayAlerts = False
        ws.Delete
        Set ws = Sheets.Add
        ws.Name = "Order Amounts"
        Application.DisplayAlerts = True
    End If
    
    ' 将工作表的标签设置成红色
    ActiveWorkbook.Sheets("Order Amounts").Tab.ColorIndex = 3
    
    ' 取行数和列数
    rowCount = Worksheets("Source Data").Cells(50000, 1).End(xlUp).Row
    columnCount = Worksheets("Source Data").Cells(rowCount, 100).End(xlToLeft).Column
    
    
    Dim pivotName As String
    pivotName = "pivot_orderAmounts"
    
    '''''''''''''''''''''''''''''''''''''''''''''''''
    ' 创建数据透视表
    '
    '  SourceData:     "Source Data" 源数据表
    '  R1C1:            第1行第1列
    '  DefaultVersion:  数据透视表版本
    '
    '''''''''''''''''''''''''''''''''''''''''''''''''
    ActiveWorkbook.PivotCaches.Add(SourceType:=xlDatabase, SourceData:= _
        "'Source Data'!R1C1:R" + CStr(rowCount) + "C" + CStr(columnCount)).CreatePivotTable TableDestination:= _
        "'[" + ThisWorkbook.Name + "]Order Amounts'!R3C1", TableName:= _
        pivotName, DefaultVersion:=xlPivotTableVersion10
    
    ' 显示数据透视表列表字段
    ActiveWorkbook.ShowPivotTableFieldList = True
    
    ' 添加数据透视表 行 字段
    With ActiveSheet.PivotTables(pivotName).PivotFields("Salesperson")
        .Orientation = xlRowField
        .Position = 1
    End With
    
    ' 添加数据透视表 数据 字段
    With ActiveSheet.PivotTables(pivotName).PivotFields("Order Amount")
        .Orientation = xlDataField
        .NumberFormat = "$#,##0.00"
    End With   
    
    ' 实际这个时候只是把源数据中的字段放到数据透视表里面,数据透视表值负责数据的展示,并没有改变任何数据
    
End Sub

 

 

好了数据透视表就建好了,那么怎么才能触发之前定义的这些方法来看到创建的数据透视表呢?这需要在Excel中建立一个按钮,在点击按钮的时候响应这些事件

 

创建按钮,先调出控制工具箱,



 

 这就是控制工具箱啦,它和工具栏上其他的工具一样,使用起来很方便,从这个工具箱里我们可以创建一个命令按钮,单击Command Button,这时光标会变成十字形状,在工作表里面空白的地方拖拽就可以画出一个 命令按钮 了,调整到合适的大小



 

注意

  • 看图中处于激活状态下的按钮 “Design Mode”,是用来控制我们创建的 命令按钮的,只有处于 设计模式 下,才可以对创建的按钮进行修改操作,也就是说如果我们要修改按钮,首先需要进入 设计模式 下才可以进行操作

 

调整按钮上的文字,右击Buttoon - 命令按钮Object - 编辑,输入Create Report,再用鼠标点击空白处就OK了。

 

一个 Button 就出来了,接下来要让点击Button响应之前定义的事件,右击按钮 - View Code

 

跳到 代码编辑器,
 

 

给一个按钮响应的事件

Sub onclick_generate()
    
    Dim rowDataObj() As dataObj
    
    getData.getRowData rowDataObj()
    
    report.CreateReport rowDataObj()
    
    
End Sub

 

 

来点下按钮试试吧,这样一个最最最最简单的数据透视表就建成了,不过知道原理和过程,要进行复杂一点的操作就容易多了。 

 

 看一下生成的 数据透视图

 

注意

  • 如果本地语言是中文的话,那么格式化后的Order Amount结果会以“¥”开头,没有关系,可以在区域和语言选项中调整成英文

 从这个数据透视图可以直接看到每个 SalesPerson 全部的 OrderAmount,很直观吧,把光标放到数据透视图中,可以看到 数据透视图字段列表,里面加粗的字段是已经反应在 数据透视表 里面的字段,普通字体的是还没有放到 透视表 中的字段



 

 

介绍一下数据透视表中的几个区域

  • 行字段区
  • 列字段区:
  • 数据字段区:放置进行统计的目标数据,比如销售额,销售量
  • Page Fields:通常用来放置过滤条件

把Country字段放到Page Fields中选择UK,就可以看到所有英国区域的销售额了



 

 

再来一个例子,在上面 report 模块代码的后面加上

    pivotName = "pivot_orderAmounts2"
    
    '''''''''''''''''''''''''''''''''''''''''''''''''
    ' 创建数据透视表
    '
    '  SourceData:     "Source Data" 源数据表
    '  R1C1:            第1行第1列
    '  DefaultVersion:  数据透视表版本
    '
    '''''''''''''''''''''''''''''''''''''''''''''''''
    ActiveWorkbook.PivotCaches.Add(SourceType:=xlDatabase, SourceData:= _
        "'Source Data'!R1C1:R" + CStr(rowCount) + "C" + CStr(columnCount)).CreatePivotTable TableDestination:= _
        "'[" + ThisWorkbook.Name + "]Order Amounts2'!R3C1", TableName:= _
        pivotName, DefaultVersion:=xlPivotTableVersion10
    
    ' 显示数据透视表列表字段
    ActiveWorkbook.ShowPivotTableFieldList = True
    
    ' 添加数据透视表 行 字段
    With ActiveSheet.PivotTables(pivotName).PivotFields("Salesperson")
        .Orientation = xlRowField
        .Position = 1
    End With
    
    ' 添加过滤字段
    With ActiveSheet.PivotTables(pivotName).PivotFields("Country")
        .Orientation = xlPageField
        .Position = 1
    End With
    With ActiveSheet.PivotTables(pivotName).PivotFields("Order Date")
        .Orientation = xlPageField
        .Position = 2
    End With
    
    ' 添加数据透视表 数据 字段
    With ActiveSheet.PivotTables(pivotName).PivotFields("Order Amount")
        .Orientation = xlDataField
        .NumberFormat = "$#,##0.00"
    End With
    
    ' 设置透视表样式
    ActiveSheet.PivotTables(pivotName).Format xlTable2
    
    ' 创建数据透视图
    Charts.Add

    ActiveChart.SetSourceData Source:=Sheets("Order Amounts2") _
        .PivotTables(pivotName).TableRange2

    ActiveChart.Location Where:=xlLocationAsNewSheet
    ActiveChart.Name = "Order Amount2 Chart"
    

 

上面的例子中添加了两个过滤字段,并且设置了一下透视表的样式



 

可以通过 ActiveSheet.PivotTables(pivotName).Format xlTable2 语句定义透视表样式,参数xlTable2参数从xlTable1到xlTable10的效果是不同的,大于10的参数小于1的样式只有一种,但不会报错。

 

这里同时还生成了一张数据透视图

 

 

 

数据透视图和透视表是一样的,它们都是以Source Data为源数据,而展现的方式不同,在透视图中也可以对字段 进行拖拽操作和过滤操作,实现起来很简单,有了源数据借助它们就能够进行深层次的分析,得到不同的结果。

 

这里有一篇通过VBA生成普通Excel的文章,有兴趣的朋友可以看一下

 Excel Chart reference:http://peltiertech.com/Excel/ChartsHowTo/QuickChartVBA.html#VBAcharts

 

 

总结一下,个人认为透视表仅仅是一种数据分析的工具,建立透视表之前关键在于对源数据的分析,怎样有效的组织源数据来达到深入分析的结果才是关键。本文中介绍的例子是非常简单的,只介绍了这个工具的使用方法,实际工作中根据需求可以创作出各种各样的不同的数据展现方式,必要的时候还有可能借用源数据来计算生成一些中间表帮助我们解决一些复杂的问题。同时,在数据量很大的时候,操作数据要小心,避免一下创建很多的对象在内存中,有时候会出现内存溢出等意想不到的结果。希望分享这些知识能帮助到有希望使用Excel生成报表的朋友。

 

 

(附件中有两个Excel文件,SampleSalespersonReports.xls是从Office Online上下载的Pivot的例子,SampleSalespersonReports_01.xls是我的文中例子,有一点小问题没有修正,第一次打开之后点击按钮会生成透视表和透视图,再次点击按钮会报错,因为透视图所在 sheet 已经存在,删除之后再点击按钮就没有问题了)

 

 

 

 

 

 

  • 大小: 28 KB
  • 大小: 2.4 KB
  • 大小: 20.9 KB
  • 大小: 11 KB
  • 大小: 6 KB
  • 大小: 12.3 KB
  • 大小: 13.8 KB
  • 大小: 10.6 KB
  • 大小: 6.3 KB
  • 大小: 325 Bytes
  • 大小: 3.7 KB
  • 大小: 6.9 KB
  • 大小: 5.3 KB
  • 大小: 646 Bytes
  • 大小: 4.4 KB
  • 大小: 9.5 KB
  • 大小: 3.4 KB
  • 大小: 5.2 KB
  • 大小: 51.6 KB
2
0
分享到:
评论
1 楼 zoumeizhong123 2013-03-06  
very good,

相关推荐

    excel 使用vba制作简单报表

    简单的报表制作,计算总支出,收入,每月可使用的招待费用计算,对财务人员日常使用提供很大的帮助

    ExCel_VBA.rar_Excel VBA_excel报表

    这个"ExCel_VBA.rar_Excel VBA_excel报表"压缩包文件显然包含了关于如何使用VBA来增强Excel报表功能的示例和教程。 首先,VBA在报表制作中的应用主要体现在以下几个方面: 1. 数据处理:通过VBA,你可以编写代码...

    VBA2048Excel试玩

    在IT领域,Excel作为一款强大的电子表格工具,被广泛应用于数据分析、报表制作等场景。而VBA(Visual Basic for Applications)作为Excel内置的编程语言,为用户提供了自定义功能和自动化操作的强大能力。本文将围绕...

    手把手教你利用VBA+excel制作IFIX报表

    手把手教你利用VBA+excel制作 IFIX 报表 可完美移植到VB6.0。 正在的手把手,一步一图,代码详解! 其中主要讲述如何判断文件、数据文件的存在、建立、修改数据、读入、写入、删除。并如何利用EXCEL模块建立报表,...

    RSView32用VBA实现excel报表实例教程_(带详细程序注释)

    ### RSView32结合VBA实现Excel报表实例教程解析 #### 一、创建ODBC数据库 **背景介绍:** 在工业自动化领域,RSView32是一款由Rockwell Automation开发的人机界面(HMI)软件,广泛应用于工厂自动化控制系统中。通过...

    VB源码 用VB制作Excel报表并自动汇总

    总结,用VB制作Excel报表并自动汇总涉及到的主要知识点包括:使用VB的Excel对象模型,如`Application`、`Workbook`、`Worksheet`和`Range`;掌握VBA的语法,包括变量声明、函数调用、循环和条件语句;理解和应用...

    进销存管理系统(Excel VBA实现)_ExcelVBA_VBa_进销存_vba进销存管理_VBA进销存

    在Excel中结合VBA(Visual Basic for Applications)实现进销存管理,可以提供一种便捷且自定义化的解决方案,尤其适合中小企业或个人使用。下面将详细介绍这种系统的基本构成和关键功能,以及VBA在其中的应用。 ...

    WPSVBA、ExcelVBA编程实例(150例).zip

    通过深入学习《WPSVBA与ExcelVBA编程实例(150例)》,你将能够熟练运用VBA进行办公自动化,无论是数据分析、报告制作还是日常办公任务,都将变得更加轻松高效。同时,这也将为你打下坚实的基础,为进一步学习其他高级...

    Excel报表汇总工具

    这款Excel报表汇总助手可能集成了上述部分或全部功能,帮助用户更加便捷地进行数据处理和报表制作,减轻工作负担,提升工作效率。在实际使用中,用户应根据自己的需求选择合适的工具和功能,以最大化利用这款软件的...

    进销存管理系统(Excel VBA实现),excel进销存管理系统下载,VBA

    在本文中,我们将深入探讨如何使用Excel和VBA(Visual Basic for Applications)来实现这样一个系统。 Excel作为一款强大的电子表格软件,因其用户友好和功能强大而被广泛应用于数据管理和分析。通过结合VBA,我们...

    Excel +VBA编写的值班排班表

    在IT行业中,尤其是在办公自动化和数据管理领域,Excel与VBA的结合应用是常见的解决方案之一。本项目"Excel + VBA编写的值班排班表"就是这样一个实例,它充分利用了Excel的强大计算和展示功能,结合VBA(Visual ...

    进销存管理系统(Excel VBA实现),excel进销存管理系统下载,VBA源码.zip

    4. **报表与分析**:提供各种统计报表,如进出库明细、库存状态、利润分析等,VBA能够生成图表,直观展示数据。 5. **用户界面**:通过VBA设计友好、易用的用户界面,使得非技术人员也能轻松操作。 6. **数据导入...

    excell_ExporToExcel.rar_Excel VBA_VBa_excel_visual basic_报表

    Excel 是一个非常优秀的报表制作软件,用VBA可以控制其生成优秀的报表,本文通过添加查询语句的方法,即用Excel中的获取外部数据的功能将数据很快地从一个查询语句中捕获到EXCEL中,比起往每个CELL里写数据的方法提高...

    Excel VBA与数据库(Access)整合笔记

    1. 数据导入导出:通过VBA脚本,自动将Access中的数据导入到Excel,或者将Excel数据保存到Access数据库中,进行数据分析或报表制作。 2. 实时数据同步:建立连接,实现实时从Access数据库获取数据更新,或者将Excel...

    WINCC通过OPC和EXCEL实现报表

    3. **Excel报表生成**: - 利用Excel强大的数据分析和图表功能,我们可以构建自动化报表。首先,建立Excel工作簿,并设置好所需的格式和公式。 - 使用Excel的VBA(Visual Basic for Applications)编程,编写宏来...

    Excel通过VBA连接Oracle数据库

    同时,你可以在VBA中创建自定义函数或过程,将这些步骤封装起来,实现一键生成报表的功能。 在给定的压缩包文件中,"Excel通过VBA连接Oracle数据库V1.0.xls"可能是一个包含此类功能的示例Excel文件,你可以打开并...

    excel2007VBA参考大全示例

    通过这个"Excel 2007 VBA参考大全示例",你可以逐步深入学习和实践Excel VBA编程,从而提升你在数据分析、报表制作和办公自动化方面的能力。每个示例都将为你提供具体的代码实现,帮助你理解并掌握各种VBA技巧。无论...

    【亲测超好用】通用2003/2007/2010Excel库存管理系统 最好用的Excel出入库管理表格 带VBA源代码,代码公开

    包含仓库货物做账用到的入库、出库、汇总、报表等全部功能,适合绝大部分的仓库、商铺、网店的出入库管理,简单易用,不需要ERP软件的基础,甚至不需要EXCEL太多知识; 使用前提:本表格使用VBA编程完成出入库的自动...

Global site tag (gtag.js) - Google Analytics