Mac에서 VBA(Excel) 사전?
Windows Scripting Dictionary 개체를 많이 사용하는 Excel VBA 프로젝트가 있습니다.최근에 Mac에서 사용하려고 시도한 사용자에게 다음 오류가 발생했습니다.
Compile Error: Can't find project or library
다음 중 어떤 것이 사용의 결과입니까?Tools > References > Microsoft Scripting Runtime
도서관.
제 질문은 Mac에서 이 작업을 수행할 수 있는 방법이 있습니까?
가능한 해결책으로 생각할 수 있는 세 가지 경우는 다음과 같습니다.
- Mac에서 사전을 사용할 수 있는 Mac 플러그인 사용(사전이 있는 경우 가장 좋아하는 옵션)
다음과 같은 종류의 변수 스위치를 수행합니다.
isMac = CheckIfMac If isMac Then ' Change dictionary variable to some other data type that is Mac friendly and provides the same functionality End If
동일한 작업을 수행하기 위해 완전히 별도의 루틴 2개를 작성합니다(이런 일이 발생하지 않도록 하십시오).
isMac = CheckIfMac If isMac Then DoTheMacRoutine Else DoTheWindowsRoutine End If
링크가 손상되지 않도록 주석에서 답변을 끌어옵니다.
Patrick O'Beirne @ sysmod는 이 문제를 다루는 클래스 세트를 작성했습니다.감사의 말을 전하기 위해 Patirk의 블로그에 꼭 들러보세요!또한 그가 더 새로운 버전을 가지고 있을 가능성도 있습니다.
save this as a plain text file named KeyValuePair.cls and import into ExcelVERSION 1.0 CLASS
BEGIN
MultiUse = -1 'True
END
Attribute VB_Name = "KeyValuePair"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = False
Option Explicit
'Unrestricted class just to hold pairs of values together and permit Dictionary object updating
Public Key As String
Public value As Variant
save this as a plain text file named Dictionary.cls and import into excel
VERSION 1.0 CLASS
BEGIN
MultiUse = -1 'True
END
Attribute VB_Name = "Dictionary"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = False
Option Explicit
'Collection methods: Add, Count, Item, Remove
'Dictionary : .Add(Key as string, Item as variant), .CompareMode, .Count, .Exists(Key); _
.Item(Key) - writeable, .Items, .Keys, .Remove(Key), .RemoveAll
'plus KeyValuePairs collection, KeyValuePair(Index as long), Tag as variant
' 25-11-2011 KeyValuePair helper object
Public KeyValuePairs As Collection ' open access but allows iteration
Public Tag As Variant ' read/write unrestricted
Private Sub Class_Initialize()
Set KeyValuePairs = New Collection
End Sub
Private Sub Class_Terminate()
Set KeyValuePairs = Nothing
End Sub
' in Scripting.Dictionary this is writeable, here we have only vbtextCompare because we are using a Collection
Public Property Get CompareMode() As VbCompareMethod
CompareMode = vbTextCompare '=1; vbBinaryCompare=0
End Property
Public Property Let Item(Key As String, Item As Variant) ' dic.Item(Key) = value ' update a scalar value for an existing key
Let KeyValuePairs.Item(Key).value = Item
End Property
Public Property Set Item(Key As String, Item As Variant) ' Set dic.Item(Key) = value ' update an object value for an existing key
Set KeyValuePairs.Item(Key).value = Item
End Property
Public Property Get Item(Key As String) As Variant
AssignVariable Item, KeyValuePairs.Item(Key).value
End Property
' Collection parameter order is Add(Item,Key); Dictionary is Add(Key,Item) so always used named arguments
Public Sub Add(Key As String, Item As Variant)
Dim oKVP As KeyValuePair
Set oKVP = New KeyValuePair
oKVP.Key = Key
If IsObject(Item) Then
Set oKVP.value = Item
Else
Let oKVP.value = Item
End If
KeyValuePairs.Add Item:=oKVP, Key:=Key
End Sub
Public Property Get Exists(Key As String) As Boolean
On Error Resume Next
Exists = TypeName(KeyValuePairs.Item(Key)) > "" ' we can have blank key, empty item
End Property
Public Sub Remove(Key As String)
'show error if not there rather than On Error Resume Next
KeyValuePairs.Remove Key
End Sub
Public Sub RemoveAll()
Set KeyValuePairs = Nothing
Set KeyValuePairs = New Collection
End Sub
Public Property Get Count() As Long
Count = KeyValuePairs.Count
End Property
Public Property Get Items() As Variant ' for compatibility with Scripting.Dictionary
Dim vlist As Variant, i As Long
If Me.Count > 0 Then
ReDim vlist(0 To Me.Count - 1) ' to get a 0-based array same as scripting.dictionary
For i = LBound(vlist) To UBound(vlist)
AssignVariable vlist(i), KeyValuePairs.Item(1 + i).value ' could be scalar or array or object
Next i
Items = vlist
End If
End Property
Public Property Get Keys() As String()
Dim vlist() As String, i As Long
If Me.Count > 0 Then
ReDim vlist(0 To Me.Count - 1)
For i = LBound(vlist) To UBound(vlist)
vlist(i) = KeyValuePairs.Item(1 + i).Key '
Next i
Keys = vlist
End If
End Property
Public Property Get KeyValuePair(Index As Long) As Variant ' returns KeyValuePair object
Set KeyValuePair = KeyValuePairs.Item(1 + Index) ' collections are 1-based
End Property
Private Sub AssignVariable(variable As Variant, value As Variant)
If IsObject(value) Then
Set variable = value
Else
Let variable = value
End If
End Sub
Public Sub DebugPrint()
Dim lItem As Long, lIndex As Long, vItem As Variant, oKVP As KeyValuePair
lItem = 0
For Each oKVP In KeyValuePairs
lItem = lItem + 1
Debug.Print lItem; oKVP.Key; " "; TypeName(oKVP.value);
If InStr(1, TypeName(oKVP.value), "()") > 0 Then
vItem = oKVP.value
Debug.Print "("; CStr(LBound(vItem)); " to "; CStr(UBound(vItem)); ")";
For lIndex = LBound(vItem) To UBound(vItem)
Debug.Print " (" & CStr(lIndex) & ")"; TypeName(vItem(lIndex)); "="; vItem(lIndex);
Next
Debug.Print
Else
Debug.Print "="; oKVP.value
End If
Next
End Sub
'NB VBA Collection object index is 1-based, scripting.dictionary items array is 0-based
'cf Scripting.Dictionary Methods s.Add(Key, Item), s.CompareMode, s.Count, s.Exists(Key); _
s.Item(Key) - updateable, s.Items, s.Key(Key), s.Keys, s.Remove(Key), s.RemoveAll
'Scripting.Dictionary has no index number; you can index the 0-based variant array of Items returned
' unlike Collections which can be indexed starting at 1
'Efficient iteration is For Each varPair in thisdic.KeyValuePairs
'Another difference I introduce is that in a scripting.dictionary, the doc says
' If key is not found when changing an item, a new key is created with the specified newitem.
' If key is not found when attempting to return an existing item, a new key is created and its corresponding item is left empty.
'but I want to raise an error when addressing a key that does not exist
'similarly, the scripting.dictionary will create separate integer and string keys for eg 2
Mac의 MS Office 2016에서는 Patirk의 구현이 작동하지 않습니다.저는 팀 홀의 구현을 활용했습니다.링크는 다음과 같습니다. https://github.com/VBA-tools/VBA-Dictionary
또한 2017년 9월 현재 맥의 MS Office 2016에서는 cls 파일을 엑셀로 Import할 수 없습니다.그래서 클래스 모듈을 만들고 Dictionary.cls에서 메타 정보를 제거하는 동안 Dictionary.cls의 내용을 수동으로 복사하여 붙여넣어야 했습니다.VERSION 1.0 CLASS
,BEGIN
,END
,Attribute
.
저는 마침내 맥용 엑셀 2016의 파일을 업데이트했습니다. http://www.sysmod.com/Dictionary.zip (사전의 대문자 D)
압축을 풀고 클래스 파일을 가져옵니다(Excel 2016에서 Mac용 16.13 빌드 424, 27-Apr-2018에서 테스트됨).
MS에 대한 버그 보고서는 answers.microsoft.com 에 있습니다. Mac 사용자 정의 클래스의 경우 매개 변수로 전달됩니다. 모든 속성이 Null입니다.
다른 것을 놓친 것이 있으면 알려주세요!행운을 빌어요,
패트릭 오베른
언급URL : https://stackoverflow.com/questions/19869266/vba-excel-dictionary-on-mac
'programing' 카테고리의 다른 글
회전된 xtick 라벨과 해당 xtick 라벨 정렬 (0) | 2023.07.01 |
---|---|
Oracle에서 Dapper QueryMultiple 사용 (0) | 2023.07.01 |
VBA에서 As를 사용하여 유형을 지정하여 여러 변수를 선언하는 방법은 무엇입니까? (0) | 2023.07.01 |
SQL Server 프로시저가 목록 선언 (0) | 2023.07.01 |
충돌 분석을 사용하여 치명적이지 않은 예외를 기록하는 방법 (0) | 2023.07.01 |