【问题标题】:Automate creation of charts in multiple excel files?在多个 Excel 文件中自动创建图表?
【发布时间】:2016-10-24 06:10:12
【问题描述】:

我刚刚花费大量时间在几十个 excel 文件中创建相同的图表(所有文件都包含相同格式的数据),并且相信必须有一种更有效的方法来完成我刚刚完成的工作。

为简化起见,请考虑 50 个具有相同格式数据的 Excel 文档。 是否存在自动的方法:

  • 创建简单的折线图
  • 添加轴标签、图表标签、删除水平网格线
  • 包括趋势线/R^2 值
  • 将新工作簿保存到特定位置,并在文件名后附加“_graphed”

这是可以使用 Excel VBA 的东西吗?

【问题讨论】:

  • 是的,注意第 1-3 点,肯定会节省我的时间。不过,理想情况下,我会寻找进一步自动化的东西。例如,我正在处理的文档的文件名(例如“aviation_accidents.csv”包含我最终传递给图表轴和标题的信息(x:“日期”y:“航空事故的标准化搜索量'", Title: "时间序列,用于“航空事故”的规范化搜索量)。如果有一个解决方案可以本质上将文件名作为输入变量并在创建图表时使用它,那就太好了。
  • 非常好,我没有想到我可以从工作簿中提取文件名。效果很好。

标签: excel automation


【解决方案1】:

对于这类问题,我会先将您手动执行的步骤的宏记录到personal macro workbook 中。然后,您可以查看 Excel 生成的代码,您可能会发现无需进行太多更改即可将其用作通用过程。

测试后,如果您想进一步实现自动化,您可以编写一个小程序来遍历目录中的所有 Excel 文件,并在每个文件打开时调用您的图表程序。如果有帮助,我可以挖掘出我编写的类似代码。

更新 Here 是一个线程,我在其中提供了一些代码来遍历包含某些给定文本的所有文件(在此示例中为“.pdf”,但也可以很容易地使用“.xls”来涵盖 xlsx、xlsm 等)。

此示例还将其找到的文件列表打印到工作表中。这是测试结果的良好开端,但一旦没问题,您就需要更换该行:

Range(c).Offset(j, 0).Value = vFileList(i)

使用一些代码打开该工作簿并调用您的代码来生成图表。如果您遇到困难,请告诉我。

进一步更新

我已经查看了上面提到的代码并进行了一些改进,包括一个附加参数,用于指定要针对每个打开的工作簿(满足指定条件)运行的宏的名称。您在调用中使用的宏必须存在于您从中调用所有其他工作簿的工作簿中(例如,如果图表宏在您的个人工作簿中,那么下面的代码也应该放在您的个人宏工作簿中):

Option Explicit

Sub FileLoop(pDirPath As String, _
             Optional pPrintToSheet = False, _
             Optional pStartCellAddr = "$A$1", _
             Optional pCheckCondition = False, _
             Optional pFileNameContains = "xxx", _
             Optional pProcToRunOnWb)

On Error GoTo PrintFileList_err

    ' Local constants / variables
    Const cProcName = "FileLoop"
    Dim vFileList() As String ' array for file names
    Dim i As Integer          ' iterator for file name array
    Dim j As Integer          ' match counter
    Dim c As String
    ' variables for optional param pProcToRunOnWb
    Dim vFullPath As String
    Dim vTmpPath As String
    Dim wb As Workbook

    vFullPath = Application.ThisWorkbook.FullName
    vFileList = GetFileList(pDirPath)
    c = pStartCellAddr
    j = 0

    For i = LBound(vFileList) To UBound(vFileList)
        ' if condition is met (i.e. filename cotains text or condition is not required...
        If pCheckCondition And InStr(1, vFileList(i), pFileNameContains, vbTextCompare) > 0 _
           Or Not pCheckCondition Then

            ' print name to sheet if required...
            If pPrintToSheet Then
                Range(c).Offset(j, 0).Value = vFileList(i)
                j = j + 1 ' increment row offset
            End If

            ' open wb to run macro if required...
            If pProcToRunOnWb <> "" Then
                Application.DisplayAlerts = False ' set alerts off so that macro can run in other wb
                vTmpPath = pDirPath & "\" & vFileList(i)
                Set wb = Workbooks.Open(Filename:=vTmpPath)
                Workbooks(wb.Name).Activate
                Application.Run "'" & vFullPath & "'!" & pProcToRunOnWb
                wb.Close (True) ' save and close workbook
                Application.DisplayAlerts = True ' set alerts back on
            End If

        End If

        Debug.Print vFileList(i)
    Next i

   ' clean up
   Set wb = Nothing

PrintFileList_exit:
    Exit Sub

PrintFileList_err:
    Debug.Print "Error in ", cProcName, vbCrLf, "Err no: ", Err.Number, _
                vbCrLf, "Err Description: ", Err.Description
    Resume Next

End Sub

Function GetFileList(pDirPath As String) As Variant
On Error GoTo GetFileList_err

    ' Local constants / variables
    Const cProcName = "GetFileList"
    Dim objFSO As Object
    Dim objFolder As Object
    Dim objFile As Object
    Dim c As Double           ' upper bound for file name array
    Dim i As Double           ' iterator for file name array
    Dim vFileList() As String ' array for file names

    Set objFSO = CreateObject("Scripting.FileSystemObject")
    Set objFolder = objFSO.GetFolder(pDirPath)
    c = objFolder.Files.Count
    i = 0

    ReDim vFileList(1 To c)  ' set bounds on file array now we know count

    'Loop through the Files collection
    For Each objFile In objFolder.Files
        'Debug.Print objFile.Name
        i = i + 1
        vFileList(i) = objFile.Name
    Next

    'Clean up!
    Set objFolder = Nothing
    Set objFile = Nothing
    Set objFSO = Nothing

    GetFileList = vFileList

GetFileList_exit:
    Exit Function

GetFileList_err:
    Debug.Print "Error in ", cProcName, vbCrLf, "Err no: ", Err.Number, _
                vbCrLf, "Err Description: ", Err.Description
    Resume Next

End Function

您可以从另一个宏或立即窗口 (ctrl+G) 调用它,并使用所需的参数,例如获取所有包含“.xls”的文件,并运行一个名为“your_macro_name_here”的宏,代码如下:

call FileLoop("C:\Users\Prosserc\Dropbox\Docs\Stack_Overflow\Test", False, "", True, ".xls", "your_macro_name_here")

显然将第一个参数中的路径更改为指向包含要对其运行宏的文件的目录。

【讨论】:

  • 我能够使用您(和 pnuts 的)建议来处理文件中发生的所有事情,但我认为您需要最后一步是正确的。如果不是太不方便的话,我会喜欢那段代码!
  • @nitrl 我已经在上面发布了更新。最初我只是包含一个指向我提到的线程的链接,然后认为最好有一个带有额外参数的代码版本来针对循环中的所有工作簿运行宏,所以发布了一个新版本的代码以上。让我知道你的进展如何。
【解决方案2】:

pythonperl 都有一个名为 Xlsxwriter 的库,可以自动生成图表。一些示例python代码,请参阅我的帖子here

【讨论】:

    猜你喜欢
    • 2013-07-31
    • 2020-01-03
    • 2021-08-08
    • 2022-11-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-18
    • 2017-04-16
    相关资源
    最近更新 更多