创建通用引用表:是一个正确的方法集合?

时间:2013-09-28 04:38:50

标签: excel excel-vba vba

我创建了一对可重复使用的子例程,这些子例程一起工作以根据需要保存不同扩展名的文件。

第一个Sub接收目录路径,文件名和所需的Excel扩展名。然后它调用第二个Sub来查找正确的Excel FileFormat数字并使用它以新格式保存文件:

Sub SaveFileWithNewExtension(DirectoryPath As String, NameOfFile As String, ExtensionToUse As String)
    Dim ExcelFileFormatNumber As String
    GetExcelFormatNumber ExtensionToUse, ExcelFileFormatNumber
    ActiveWorkbook.SaveAs DirectoryPath & "\" & NameOfFile & ExtensionToUse, FileFormat:=ExcelFileFormatNumber
End Sub

第二个子主要是我将使用的Excel FileFormats的参考。对于FileFormat引用,我将FileFormat Number和Name存储在一个键入不同文件扩展名的数组中,所有这些都存储在我可以根据需要添加的集合中:

Sub GetExcelFormatNumber(Extension As String, Optional Number As String, Optional ExcelFormat As String)
    'http://msdn.microsoft.com/en-us/library/office/ff198017.aspx
    'http://www.rondebruin.nl/mac/mac020.htm
    Dim ExtensionReference As New Collection
    ExtensionReference.Add Array("51", "xlOpenXMLWorkbook"), ".xlsx"
    ExtensionReference.Add Array("52", "xlOpenXMLWorkbookMacroEnabled"), ".xlsm"
    ExtensionReference.Add Array("50", "xlExcel12"), ".xlsb"
    ExtensionReference.Add Array("56", "xlExcel8"), ".xls"

    On Error GoTo NoMatch:
    ExcelFormat = ExtensionReference.Item(Extension)(1)
    Number = ExtensionReference.Item(Extension)(0)
    Exit Sub

NoMatch:
    msgbox "No Matching Extension was Found in the ExcelExtensionsAndNumbers Collection"

End Sub

将数组保存在这样的集合中似乎相当笨重而且不优雅,这让我觉得我已经这么做了。

这是我的问题: 是否有更好的方法来存储信息,如供其他潜艇使用?或者用另一种方式表达:你是否有一种最喜欢抽象数据的方式(比如本例中的FileFormat代码),所以它可以重复使用而不必每次都记住和重写它?


代码已被修改为使用案例而不是集合,以更好地处理错误(正如Siddharth Rout重写代码所建议的那样)。这是有效的,案例结构对我的眼睛更有意义:

Public Sub SaveFileWithNewExtension(DirectoryPath As String, NameOfFile As String, ExtensionToUse As String)
    Dim ExcelFileFormatNumber As String
    GetExcelFormatNumber ExtensionToUse, ExcelFileFormatNumber
    If ExcelFileFormatNumber <> "" Then
        ActiveWorkbook.SaveAs DirectoryPath & "\" & NameOfFile & ExtensionToUse, FileFormat:=ExcelFileFormatNumber
    Else
        msgbox "Invalid file extension. Case does not exist."
    End If
End Sub


Public Sub GetExcelFormatNumber(ExtensionToFind As String, Optional Number As String, Optional ExcelFormat As String)
    'reference - http://msdn.microsoft.com/en-us/library/office/ff198017.aspx
    'reference - http://www.rondebruin.nl/mac/mac020.htm
        Select Case ExtensionToFind
            Case ".xlsx":   Number = "51"
                            ExcelFormat = "xlOpenXMLWorkbook"
            Case ".xlsm":   Number = "52"
                            ExcelFormat = "xlOpenXMLWorkbookMacroEnabled"
            Case ".xlsb":   Number = "50"
                            ExcelFormat = "xlExcel12"
            Case ".xls":    Number = "56"
                            ExcelFormat = "xlExcel8"
            Case ".csv":    Number = "6"
                            ExcelFormat = "xlCSV"
            Case Else:      Number = ""
                            ExcelFormat = ""
        End Select
End Sub

2 个答案:

答案 0 :(得分:1)

我同意。对于4个Extns,数组将是一个过度杀伤。我宁愿在函数中使用Select Case。见下文

UNTESTED

Sub SaveFileWithNewExtension(DirectoryPath As String, _
                             NameOfFile As String, _
                             ExtensionToUse As String)
    Dim ExcelFileFormatNumber As Long
    ExcelFileFormatNumber = GetExcelFormatNumber(ExtensionToUse)

    If ExcelFileFormatNumber <> 0 Then
        ActiveWorkbook.SaveAs _
        DirectoryPath & _
        "\" & _
        NameOfFile & ExtensionToUse, _
        FileFormat:=ExcelFileFormatNumber
    Else
        MsgBox "Invalid Extenstion:"
    End If
End Sub

Function GetExcelFormatNumber(Extn As String) As Long
    '~~> FileFormat
    Select Case UCase(Extn)
        Case "XLS": GetExcelFormatNumber = 56
        Case "XLSX": GetExcelFormatNumber = 51
        Case "XLSM": GetExcelFormatNumber = 52
        Case "XLSB": GetExcelFormatNumber = 56
        '~~> Add for more... like csv etc
    End Select
End Function

答案 1 :(得分:0)

这是一个相当普遍的解决方案(从Excel 2010开始):

Function GetFileFormat(FileExt As String) As Long
    'Converts the specified file-extension string to its corresponding file-format code value, if known.  If the
    'file-format value for the specified extension is unknown, then a zero value is returned.
    '
    'WARNING: some extension strings map to multiple possible file-format values.  Such ambiguous specifications
    'are handled according to the following priority:
    '
    '   1) If the ambiguity is related to older vs. more recent versions of the file type, such as xlDBF4
    '      vs. xlDBF3 vs. xlDBF2, the most recent version is returned (xlDBF4).
    '
    '   2) If the ambiguity is related to more general vs. more specific versions of the file type, such as
    '       xlCurrentPlatformText vs. xlTextMSDOS vs. xlTextWindows and there is a Excel version-specific default
    '       option (xlCurrentPlatformText in this case) then the version-specific default is returned.
    '
    '   3) If the ambiguity is related to more general vs. more specific versions and there is no Excel version-
    '      specific default, such as xlCSV vs. xlCSVMSDOS vs. xlCSVWindows, the most general version is returned
    '      (xlCSV).
    '
    '   4) "xls" files present a special case of all of the above.  See the code commentary for that
    '      case, below.
    '
    '   If you need a different default conversion, then edit the code accordingly.
    '
    'NOTE: Though they should all work in theory, based on the available reference documentation, not all of
    '      these conversions have been tested (as of August 2014)!
    '
    'AUTHOR: Peter Straton
    '
    '*************************************************************************************************************

    'The following FileFormat constants are available in all versions from Excel 2003 onward, so they are listed
    'here for reference but there is no need to actually declare them.  If there is a possibility of running this
    'code under an earlier version of Excel, then experiment and un-comment any undefined constants.

    'Const xlAddIn                       As Long = 18    '.xla
    'Const xlAddIn8                      As Long = 18    '.xla
    'Const xlCSV                         As Long = 6     '.csv
    'Const xlCSVMac                      As Long = 22    '.csv
    'Const xlCSVMSDOS                    As Long = 24    '.csv
    'Const xlCSVWindows                  As Long = 23    '.csv
    'Const xlCurrentPlatformText         As Long = -4158 '.txt
    'Const xlDBF2                        As Long = 7     '.dbf
    'Const xlDBF3                        As Long = 8     '.dbf
    'Const xlDBF4                        As Long = 11    '.dbf
    'Const xlDIF                         As Long = 9     '.dif
    'Const xlExcel12                     As Long = 50    '.xlsb
    'Const xlExcel2                      As Long = 16    '.xls
    'Const xlExcel2FarEAst               As Long = 27    '.xls
    'Const xlExcel3                      As Long = 29    '.xls
    'Const xlExcel4                      As Long = 33    '.xls
    'Const xlExcel4Workbook              As Long = 35    '.xlw
    'Const xlExcel5                      As Long = 39    '.xls
    'Const xlExcel7                      As Long = 39    '.xls
    'Const xlExcel8                      As Long = 56    '.xls
    'Const xlExcel9795                   As Long = 43    '.xls
    'Const xlHtml                        As Long = 44    '.htm, .html
    'Const xlIntlAddIn                   As Long = 26    '
    'Const xlIntlMacro                   As Long = 25    '
    'Const xlNormal                      As Long = -4143 '
    'Const xlOpenDocumentSpreadsheet     As Long = 60    '.ods
    'Const xlOpenXMLAddIn                As Long = 55    '.xlam
    'Const xlOpenXMLTemplate             As Long = 54    '.xltx
    'Const xlOpenXMLTemplateMacroEnabled As Long = 53    '.xltm
    'Const xlOpenXMLWorkbook             As Long = 51    '.xlsx
    'Const xlOpenXMLWorkbookMacroEnabled As Long = 52    '.xlsm
    'Const xlSYLK                        As Long = 2     '.slk
    'Const xlTemplate                    As Long = 17    '.xlt
    'Const xlTemplate8                   As Long = 17    '.xlt
    'Const xlTextMac                     As Long = 19    '.txt
    'Const xlTextMSDOS                   As Long = 21    '.txt
    'Const xlTextPrinter                 As Long = 36    '.prn
    'Const xlTextWindows                 As Long = 20    '.txt
    'Const xlUnicodeText                 As Long = 42    '.txt
    'Const xlWebArchive                  As Long = 45    '.mht, .mhtml
    'Const xlWJ2WD1                      As Long = 14    '
    'Const xlWJ3                         As Long = 40    '
    'Const xlWJ3FJ3                      As Long = 41    '
    'Const xlWK1                         As Long = 5     '.wk1
    'Const xlWK1ALL                      As Long = 31    '.wk1
    'Const xlWK1FMT                      As Long = 30    '.wk1
    'Const xlWK3                         As Long = 15    '.wk3
    'Const xlWK3FM3                      As Long = 32    '.wk3
    'Const xlWK4                         As Long = 38    '.wk4
    'Const xlWKS                         As Long = 4     '.wks
    'Const xlWorkbookDefault             As Long = 51    '.xlsx
    'Const xlWorkbookNormal              As Long = -4143 '
    'Const xlWorks2FarEAst               As Long = 28    '.wks
    'Const xlWQ1                         As Long = 34    '.wq1
    'Const xlXMLData                     As Long = 47    '.xml
    'Const xlXMLSpreadsheet              As Long = 46    '.xml

    'The following FileFormat constants are not available in any versions of Excel up to and including Excel 2010,
    '(VBA7) so declare them in all cases.

    Const xlOpenXMLStrictWorkbook       As Long = 61    '.??? (Exists in Excel 2013 and later versions)
    Const UnsupportedPDF                As Long = 57    'As of 8/2014, this value works while debugging in VBE but
                                                        'fails otherwise!

    'The following FileFormat constants are not available in versions of Excel prior to Excel 2007 (VBA7),
    'so declare them in all versions earlier than VBA7.

    #If VBA7 = 0 Then   'Can't use the "Not" operator since defined built-in compiler constants evaluate
                        'to 1 (&H0001), not True (&HFFFF).  So (Not 1) = &HFFFE, which is also True since it
                        'isn't &H0000 (False).

        Const xlAddIn8                      As Long = 18    '.xla
        Const xlExcel12                     As Long = 50    '.xlsb
        Const xlExcel8                      As Long = 56    '.xls
        Const xlOpenDocumentSpreadsheet     As Long = 60    '.ods
        Const xlOpenXMLAddIn                As Long = 55    '.xlam
        Const xlOpenXMLTemplate             As Long = 54    '.xltx
        Const xlOpenXMLTemplateMacroEnabled As Long = 53    '.xltm
        Const xlOpenXMLWorkbook             As Long = 51    '.xlsx
        Const xlOpenXMLWorkbookMacroEnabled As Long = 52    '.xlsm
        Const xlTemplate8                   As Long = 17    '.xlt
        Const xlWorkbookDefault             As Long = 51    '.xlsx
    #End If

    'Though web references suggest xlXMLData should be defined in Excel 2003 (VBA6) only, it isn't actually
    'defined in my copy of VBA6, running under Excel 2003.  So don't actually restrict this declaration to
    'versions later than Excel 2003.

'    #If VBA6 = 0 And VBA7 = 1 Then 'All versions later than Excel 2003 (See note about "Not" operator, above)

        Const xlXMLData                     As Long = 47    '.xml
'    #End If

    Select Case UCase(Replace(FileExt, ".", ""))
        Case "CSV": GetFileFormat = xlCSV
        Case "DBF": GetFileFormat = xlDBF4
        Case "DIF": GetFileFormat = xlDIF
        Case "HTM": GetFileFormat = xlHtml
        Case "HTML": GetFileFormat = xlHtml
        Case "MHT": GetFileFormat = xlWebArchive
        Case "MHTML": GetFileFormat = xlWebArchive
        Case "ODS": GetFileFormat = xlOpenDocumentSpreadsheet
        Case "PDF": GetFileFormat = UnsupportedPDF
        Case "PRN": GetFileFormat = xlTextPrinter
        Case "SLK": GetFileFormat = xlSYLK
        Case "TXT": GetFileFormat = xlCurrentPlatformText
        Case "WK1": GetFileFormat = xlWK1ALL
        Case "WK3": GetFileFormat = xlWK3FM3
        Case "WK4": GetFileFormat = xlWK4
        Case "WKS": GetFileFormat = xlWKS
        Case "WQ1": GetFileFormat = xlWQ1
        Case "XLA": GetFileFormat = xlAddIn
        Case "XLAM": GetFileFormat = xlOpenXMLAddIn
        Case "XLS"
            If CInt(Application.Version) >= Excel_2007_VNum Then
                'Excel 2007 and later versions:

                GetFileFormat = xlExcel8                   '= 56, an ".xls" file
            Else
                'Excel 2003:

                'The xlExcel8 value (56) isn't actually recognized by Excel versions 8 through 11 (Excel 97
                'through 2003), so use of it will fail.  And, the default used when the SaveAs method's
                'FileFormat argument isn't defined (for either a new file or existing) is the file format
                'of the last successfully saved file, whatever that might be!  (Note that Excel VBA Help is
                'misleading on this point.)  So, in this case, return xlNormal (-4143) which always defaults
                'to an ".xls" file type when the code is run under Excel 2003 and earlier versions.

                GetFileFormat = xlNormal                   'defaults to an ".xls" file
            End If
        Case "XLSB": GetFileFormat = xlExcel12
        Case "XLSM": GetFileFormat = xlOpenXMLWorkbookMacroEnabled
        Case "XLSX": GetFileFormat = xlOpenXMLWorkbook
        Case "XLT": GetFileFormat = xlTemplate
        Case "XLTM": GetFileFormat = xlOpenXMLTemplateMacroEnabled
        Case "XLTX": GetFileFormat = xlOpenXMLTemplate
        Case "XLW": GetFileFormat = xlExcel4Workbook
'        Case "XML": GetFileFormat = xlXMLData          'Which would be the best default?
        Case "XML": GetFileFormat = xlXMLSpreadsheet    '   "
    End Select

    #If Mac Then
        If CInt(Application.Version) > Excel_Mac2011_VNum Then
            'This code is running on a Mac and this is Excel 2011 or a later version

            'Per Ron de Bruin @http://www.rondebruin.nl/mac/mac020.htm, in Excel 2011 (Mac) you must add 1 to
            'each FileFormat value. [Untested]

            FileFormatCode = FileFormatCode + 1
        End If
    #End If
End Function

正如代码中所述,所有转换都应该在理论上基于可用的参考文档工作,但并非所有转换都经过测试(截至2014年8月)。任何有关彻底测试的帮助将不胜感激。如果发现任何错误的转换,请在此处发布回复,并将更正更正。