使用 VBA/宏在 Excel 中创建图形

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8345167/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 12:15:38  来源:igfitidea点击:

Creating graph in Excel using VBA/macro

excel-vbagraphaccess-vbavbaexcel

提问by Nupur

I created a macro in Excel for creating bar graphs automatically. Whenever I run it, it gives "smr run time error" and I am not able to figure out what is wrong with my code.

我在 Excel 中创建了一个宏,用于自动创建条形图。每当我运行它时,它都会给出“smr 运行时错误”,我无法弄清楚我的代码有什么问题。

Sub CreateGraph()
'
' CreateGraph Macro
''Initialize variables
Dim lastRow As Integer
Dim xlsPath As String
Dim xlsFile As String
xlsPath = "H:\"
xlsFile = "text.xls"
Workbooks.Open Filename:=xlsPath & xlsFile

    ActiveWindow.SmallScroll Down:=-81
    Range("A1:B" & lastRow).Select
    ActiveSheet.Shapes.AddChart.Select
    ActiveChart.SetSourceData Source:=Range("'TEST'!$A:$B" & lastRow)
    ActiveChart.ChartType = xlBarClustered
    ActiveChart.Axes(xlCategory).Select
    ActiveSheet.ChartObjects("Chart 2").Activate
    ActiveChart.Axes(xlCategory).ReversePlotOrder = True
    Range("Q111").Select
    ActiveWorkbook.Save
ActiveWorkbook.Close
End Sub

Can anyone help me in solving this puzzle please. Also for running any macro automatically from SAS, I always have to change the Excel options for "enable all macros" which I suppose is not good. I have seen people creating and running macros without doing this. Can you please tell me how can I run the macros with enabling all macros option in Excel.

谁能帮我解决这个难题。同样为了从 SAS 自动运行任何宏,我总是必须更改“启用所有宏”的 Excel 选项,我认为这并不好。我见过有人在不这样做的情况下创建和运行宏。你能告诉我如何在 Excel 中启用所有宏选项来运行宏。

回答by Tony Dallimore

The code within this version of the answer is essentially unchanged from the previous version. However, the text has been rewritten to (1) describe my experience of this type of project, (2) answer the true question and (3) better explain the solution.

此版本答案中的代码与先前版本基本相同。但是,文本已被重写为 (1) 描述我在此类项目中的经验,(2) 回答真正的问题,以及 (3) 更好地解释解决方案。

My experience of this type of project

我对此类项目的经验

I have been involved in five such projects. In each case, the client believed they required the automatic creation of charts but detailed discussion revealed that that this was not the requirement. The clients all published a substantial number of charts per month but most of the charts were the same as last month but with new data. They needed to automate the provision of new data for the charts. Every month some charts were revised but this was humans agreeing better ways of presenting the data. They wanted the 90% of charts that were unchanged to go through without any effort and implementation of the revisions to be as easy as possible.

我参与了五个这样的项目。在每种情况下,客户都认为他们需要自动创建图表,但详细讨论表明这不是要求。客户每个月都发布了大量图表,但大多数图表与上个月相同,但有新的数据。他们需要自动为图表提供新数据。每个月都会修改一些图表,但这是人类同意更好的数据呈现方式。他们希望 90% 的图表无需任何努力即可完成,并且修订版的实施尽可能简单。

In this case, the questioner publishes 100 charts per month in the form of an Excel workbook. The data for these charts comes from an Access database. The solution allows for the charts to be changed easily but this is to ease the programming and not to provide more than has been requested.

在这种情况下,提问者每月以 Excel 工作簿的形式发布 100 个图表。这些图表的数据来自 Access 数据库。该解决方案允许轻松更改图表,但这是为了简化编程,而不是提供超出要求的内容。

Release Template.xls

发布模板.xls

The solution requires a hand-crafted workbook named Release Template.xls. This workbook will contain all the charts and the Month 1 data. The solution creates a copy of this workbook named Release YYMM.xls in which the Month 1 data has been overwritten by the MM/YY data.

该解决方案需要一个名为 Release Template.xls 的手工工作簿。该工作簿将包含所有图表和第 1 个月的数据。该解决方案创建了一份名为 Release YYMM.xls 的工作簿副本,其中第 1 个月的数据已被 MM/YY 数据覆盖。

Release Template.xls contains a worksheet, Params, which will be deleted from the release version. This worksheet has a title row and one data row per chart. There are five columns: Sheet Name, Range, Number of Rows, Number of Columns and SQL command.

Release Template.xls 包含一个工作表 Params,它将从发布版本中删除。此工作表的每个图表有一个标题行和一个数据行。有五列:工作表名称、范围、行数、列数和 SQL 命令。

Sheet Name and Range define the location of the source data for the chart.

工作表名称和范围定义图表源数据的位置。

Number of Rows and Number of Columns define the size of the range. These values should be generated from the range (or vice versa) but this generation is not difficult and its inclusion would complicate the answer for little advantage.

行数和列数定义了范围的大小。这些值应该从范围中生成(反之亦然),但这一生成并不困难,而且它的包含会使答案复杂化,几乎没有什么好处。

SQL command is the command to be used to extract the data for the chart from the database. The code below assumes the SQL command generates a Recordset containing data ready to drop into the worksheet.

SQL 命令是用于从数据库中提取图表数据的命令。下面的代码假设 SQL 命令生成一个包含准备放入工作表的数据的 Recordset。

These parameters could be in the Access database but I believe they fit more logically in the workbook. These parameters control getting data out of the Access database and into the Excel workbook. If a chart is changed such that it requires new data, these parameters must be changed to match but no change is required to the code.

这些参数可能在 Access 数据库中,但我相信它们在工作簿中更符合逻辑。这些参数控制从 Access 数据库和 Excel 工作簿中获取数据。如果图表发生更改,需要新数据,则必须更改这些参数以匹配,但无需更改代码。

Envelope

信封

When this code was tested, it was within an Access Module. It could probably be transferred to a form but that has not been tested. There MUST be a reference to the "Microsoft Excel 11.0 Object Library".

测试此代码时,它位于访问模块中。它可能可以转移到一种形式,但尚未经过测试。必须有对“Microsoft Excel 11.0 对象库”的引用。

This envelope should be suitable for any similar problem.

这个信封应该适用于任何类似的问题。

Option Compare Database
Option Explicit

Sub Control()

  ' This list includes the variables for the envelope and the generation code

  Dim DestFileName As String
  Dim Path As String
  Dim xlApp As Excel.Application
  Dim xlWB As Excel.Workbook

  ' I have my Excel file and my Access database in the same folder.
  ' This statement gets me the name of the folder holding my database.
  ' You may need to define a different path.
  Path = Application.CurrentProject.Path

  ' Create path and file name of "Resource YYMM.xls"
  DestFileName = Path & "\" & "Resource " & Format(Date, "yymm") & ".xls"
  ' Create copy of "Resource Template.xls".
  FileCopy Path & "\Resource Template.xls", DestFileName

  Set xlApp = New Excel.Application
  With xlApp
    .Visible = True  ' This slows the macro but helps with debugging
    ' .Visible = False
    Set xlWB = .Workbooks.Open(DestFileName)
    With xlWB      

      ' Code to amend "Resource YYMM.xls" goes here

      .Save       ' Save the amended workbook
      .Close      ' Close the amended workbook
    End With
    Set xlWB = Nothing  ' Clear reference to workbook
    .Quit               ' Quit Excel
  End With   Set xlApp = Nothing   ' Clear reference to Excel
End Sub

Code to generate copy data to workbook

生成复制数据到工作簿的代码

This code assumes it is possible to create SQL statments that will generate Recordsets of data ready to drop into the workbook.

此代码假定可以创建 SQL 语句,这些语句将生成准备放入工作簿的数据记录集。

This code has been partially tested. The tests parameters defined ranges in the workbook which matches the size of the parameters. The data loaded into Params() was written to these ranges.

此代码已部分测试。测试参数在工作簿中定义了与参数大小相匹配的范围。加载到 Params() 的数据被写入这些范围。

      Dim DestSheetName As String
      Dim NumCols As Integer
      Dim NumRows As Integer
      Dim OutData() as Variant
      Dim Params() as Variant
      Dim RngDest As String
      Dim RowParamCrnt As Integer
      Dim RowParamMax As Integer
      Dim SQLCommand As String

      With .Sheets("Params")
        ' Find last used row in worksheet
        RowParamMax = .Cells(Rows.Count,"A").End(xlUp).Row
        ' Read entire worksheet into array Params
        Params = .Range(.Cells(1, 1), .Cells(RowParamMax, 5)).Value

        xlApp.DisplayAlerts = False       ' Surpress delete confirmation
        .Delete                           ' Delete parameters sheet
        xlApp.DisplayAlerts = True

      End With    

      ' Params is an array with two dimensions.  Dimension 1 is the row.
      ' Dimension 2 is the column.  Loading Params from the range is
      ' equivalent to:
      '   ReDim Params( 1 to RowParamMax, 1 to 5)    
      '   Copy data from worksheet to array

      For RowParamCrnt = 2 To RowParamMax

        DestSheetName = Params(RowParamCrnt, 1)
        DestRng = Params(RowParamCrnt, 2)
        NumRows = Params(RowParamCrnt, 3)
        NumCols = Params(RowParamCrnt, 4)
        SQLCommand = Params(RowParamCrnt, 5)

        ' Use the SQL command to create a Recordset containing the data
        ' for the chart. 

        ' Check the Recordset's dimensions against NumRows and NumCols

        ReDim OutData(1 to NumRows, 1 to NumCols)

        ' Note (repeat Note): the first dimension is for rows and the
        ' second dimension is for columns. This is required for arrays
        ' to be read from or to a worksheet.

        ' Move the data out of the Recordset into array OutData.

        .Sheets(DestSheetName).Range(DestRng).Value = OutData

      Next