VBA의 다중 스레딩
여기 아무도 VBA가 여러 스레드를 실행하는 방법을 알고 있습니까? Excel을 사용하고 있습니다.
VBA로는 기본적으로 수행 할 수 없습니다. VBA는 단일 스레드 아파트에 구축되었습니다. 여러 스레드를 가져 오는 유일한 방법은 COM 인터페이스가있는 VBA 이외의 다른 항목에서 DLL을 빌드하고 VBA에서 호출하는 것입니다.
아마 배웠 듯이 VBA는 기본적으로 멀티 스레딩을 지원하지 않지만. 멀티 스레딩을 달성하는 방법에는 세 가지가 있습니다.
- COM / dll- 예를 들어 C # 및 Parallel 클래스를 별도의 스레드에서 실행
- VBscript 작업자 스레드 사용 -별도의 VBscript 스레드에서 VBA 코드 실행
- 예를 들어 VBscript를 통해 실행되는 VBA 작업자 스레드 사용-Excel 통합 문서를 복사하고 매크로를 병렬로 실행합니다.
여기에서 모든 스레드 접근 방식을 비교했습니다. http://analystcave.com/excel-multithreading-vba-vs-vbscript-vs-c-net/
접근 방식 # 3을 고려하여 VBA에 멀티 스레딩을 쉽게 추가 할 수있는 VBA 멀티 스레딩 도구도 만들었습니다. http://analystcave.com/excel-vba-multithreading-tool/
아래 예를 참조하십시오.
For 루프 멀티 스레딩
Sub RunForVBA(workbookName As String, seqFrom As Long, seqTo As Long)
For i = seqFrom To seqTo
x = seqFrom / seqTo
Next i
End Sub
Sub RunForVBAMultiThread()
Dim parallelClass As Parallel
Set parallelClass = New Parallel
parallelClass.SetThreads 4
Call parallelClass.ParallelFor("RunForVBA", 1, 1000)
End Sub
Excel 매크로를 비동기 적으로 실행
Sub RunAsyncVBA(workbookName As String, seqFrom As Long, seqTo As Long)
For i = seqFrom To seqTo
x = seqFrom / seqTo
Next i
End Sub
Sub RunForVBAAndWait()
Dim parallelClass As Parallel
Set parallelClass = New Parallel
Call parallelClass.ParallelAsyncInvoke("RunAsyncVBA", ActiveWorkbook.Name, 1, 1000)
'Do other operations here
'....
parallelClass.AsyncThreadJoin
End Sub
나는 비슷한 것을 찾고 있었고 공식적인 대답은 아니오입니다. 그러나 ExcelHero.com에서 Daniel의 흥미로운 개념을 찾을 수있었습니다.
기본적으로 원하는 다양한 작업을 실행하고 Excel로 다시보고하려면 작업자 vbscript를 만들어야합니다. 내가하는 일을 위해 다양한 웹 사이트에서 HTML 데이터를 검색하면 훌륭하게 작동합니다!
구경하다:
http://www.excelhero.com/blog/2010/05/multi-threaded-vba.html
프로그래머가 더 현대적인 언어에서 VBA로 이동하고 VBA에서 다중 스레딩을 위해 Stack Overflow를 검색하면 VBA의 진정한 다중 스레딩 부족을 보완하는 데 도움이되는 몇 가지 기본 VBA 접근 방식을 인식하지 못할 수 있기 때문에이 답변을 추가하고 있습니다.
멀티 스레딩의 동기가 장기 실행 코드가 실행될 때 중단되지 않는 응답 성이 더 높은 UI를 갖는 것이라면 VBA에는 실제로 작동하는 몇 가지 낮은 기술 솔루션이 있습니다.
1) 사용자 양식을 모덜리스로 표시하도록 만들 수 있습니다.이를 통해 사용자는 양식이 열려있는 동안 Excel과 상호 작용할 수 있습니다. 이것은 런타임에 Userform의 ShowModal 속성을 false로 설정하여 지정하거나 다음 줄을 입력하여로드에서 동적으로 수행 할 수 있습니다.
UserForm1.Show vbModeless
사용자 양식의 초기화 이벤트에서.
2) DoEvents 문. 이로 인해 VBA는 Excel에서 생성 된 이벤트를 포함하여 이벤트 큐의 모든 이벤트를 실행하도록 OS에 제어를 넘깁니다. 일반적인 사용 사례는 코드가 실행되는 동안 차트를 업데이트하는 것입니다. DoEvents가 없으면 매크로가 실행될 때까지 차트가 다시 그려지지 않지만 Doevents를 사용하면 애니메이션 차트를 만들 수 있습니다. 이 아이디어의 변형은 진행률 측정기를 만드는 일반적인 트릭입니다. 10,000,000 번 실행하는 루프 (루프 인덱스 i에 의해 제어 됨 )에서 다음과 같은 코드 섹션을 가질 수 있습니다.
If i Mod 10000 = 0 Then
UpdateProgressBar(i) 'code to update progress bar display
DoEvents
End If
이 중 어느 것도 멀티 스레딩이 아니지만 어떤 경우에는 적절한 클러지가 될 수 있습니다.
질문이 Excel을 지정한다는 것을 알고 있지만 Access에 대한 동일한 질문이 중복으로 표시되었으므로 여기에 답변을 게시하겠습니다. 원칙은 간단합니다. 새 Access 응용 프로그램을 연 다음 해당 응용 프로그램 내에서 타이머가있는 양식을 열고, 실행할 함수 / 서브를 해당 양식으로 보내고, 타이머에 도달하면 작업을 실행하고, 실행이 완료되면 응용 프로그램을 종료합니다. 끝마친. 이를 통해 VBA는 데이터베이스의 테이블 및 쿼리로 작업 할 수 있습니다. 참고 : 데이터베이스를 독점적으로 잠근 경우 오류가 발생합니다.
이것은 모든 VBA입니다 (다른 답변과 달리)
하위 / 함수를 비동기 적으로 실행하는 함수
Public Sub RunFunctionAsync(FunctionName As String)
Dim A As Access.Application
Set A = New Access.Application
A.OpenCurrentDatabase Application.CurrentProject.FullName
A.DoCmd.OpenForm "MultithreadingEngine"
With A.Forms("MultiThreadingEngine")
.TimerInterval = 10
.AddToTaskCollection (FunctionName)
End With
End Sub
이를 달성하는 데 필요한 양식의 모듈
(양식 이름 = MultiThreadingEngine, 컨트롤이나 속성이 설정되지 않음)
Public TaskCollection As Collection
Public Sub AddToTaskCollection(str As String)
If TaskCollection Is Nothing Then
Set TaskCollection = New Collection
End If
TaskCollection.Add str
End Sub
Private Sub Form_Timer()
If Not TaskCollection Is Nothing Then
If TaskCollection.Count <> 0 Then
Dim CollectionItem As Variant
For Each CollectionItem In TaskCollection
Run CollectionItem
Next CollectionItem
End If
End If
Application.Quit
End Sub
매개 변수에 대한 지원을 구현하는 것은 충분히 쉬워야하지만 값을 반환하는 것은 어렵습니다.
As said before, VBA does not support Multithreading.
But you don't need to use C# or vbScript to start other VBA worker threads.
I use VBA to create VBA worker threads.
First copy the makro workbook for every thread you want to start.
Then you can start new Excel Instances (running in another Thread) simply by creating an instance of Excel.Application (to avoid errors i have to set the new application to visible).
To actually run some task in another thread i can then start a makro in the other application with parameters form the master workbook.
To return to the master workbook thread without waiting i simply use Application.OnTime in the worker thread (where i need it).
As semaphore i simply use a collection that is shared with all threads. For callbacks pass the master workbook to the worker thread. There the runMakroInOtherInstance Function can be reused to start a callback.
'Create new thread and return reference to workbook of worker thread
Public Function openNewInstance(ByVal fileName As String, Optional ByVal openVisible As Boolean = True) As Workbook
Dim newApp As New Excel.Application
ThisWorkbook.SaveCopyAs ThisWorkbook.Path & "\" & fileName
If openVisible Then newApp.Visible = True
Set openNewInstance = newApp.Workbooks.Open(ThisWorkbook.Path & "\" & fileName, False, False)
End Function
'Start macro in other instance and wait for return (OnTime used in target macro)
Public Sub runMakroInOtherInstance(ByRef otherWkb As Workbook, ByVal strMakro As String, ParamArray var() As Variant)
Dim makroName As String
makroName = "'" & otherWkb.Name & "'!" & strMakro
Select Case UBound(var)
Case -1:
otherWkb.Application.Run makroName
Case 0:
otherWkb.Application.Run makroName, var(0)
Case 1:
otherWkb.Application.Run makroName, var(0), var(1)
Case 2:
otherWkb.Application.Run makroName, var(0), var(1), var(2)
Case 3:
otherWkb.Application.Run makroName, var(0), var(1), var(2), var(3)
Case 4:
otherWkb.Application.Run makroName, var(0), var(1), var(2), var(3), var(4)
Case 5:
otherWkb.Application.Run makroName, var(0), var(1), var(2), var(3), var(4), var(5)
End Select
End Sub
Public Sub SYNCH_OR_WAIT()
On Error Resume Next
While masterBlocked.Count > 0
DoEvents
Wend
masterBlocked.Add "BLOCKED", ThisWorkbook.FullName
End Sub
Public Sub SYNCH_RELEASE()
On Error Resume Next
masterBlocked.Remove ThisWorkbook.FullName
End Sub
Sub runTaskParallel()
...
Dim controllerWkb As Workbook
Set controllerWkb = openNewInstance("controller.xlsm")
runMakroInOtherInstance controllerWkb, "CONTROLLER_LIST_FILES", ThisWorkbook, rootFold, masterBlocked
...
End Sub
Sub MultiProcessing_Principle()
Dim k As Long, j As Long
k = Environ("NUMBER_OF_PROCESSORS")
For j = 1 To k
Shellm "msaccess", "C:\Autoexec.mdb"
Next
DoCmd.Quit
End Sub
Private Sub Shellm(a As String, b As String) ' Shell modificirani
Const sn As String = """"
Const r As String = """ """
Shell sn & a & r & b & sn, vbMinimizedNoFocus
End Sub
ReferenceURL : https://stackoverflow.com/questions/5721564/multi-threading-in-vba
'Program Club' 카테고리의 다른 글
| 페이징이 활성화되고 확대 / 축소 된 UIScrollView 이미지 / 사진 뷰어 (0) | 2021.01.07 |
|---|---|
| https URL의 사용자 이름 및 비밀번호 (0) | 2021.01.07 |
| SVN에서 태그와 분기의 차이점은 무엇입니까? (0) | 2021.01.07 |
| win API를 사용하여 HRESULT 값의 문자열 표현을 얻는 방법이 있습니까? (0) | 2021.01.07 |
| datetime.datetime을 datetime.date와 비교할 수 없습니다. (0) | 2021.01.07 |