VBA의 멀티스레딩
여기 VBA가 여러 스레드를 실행하도록 하는 방법을 아는 사람이 있습니까?저는 엑셀을 사용하고 있습니다.
VBA로는 기본적으로 수행할 수 없습니다.VBA는 싱글 스레드 아파트에 구축됩니다.여러 스레드를 가져오는 유일한 방법은 COM 인터페이스가 있는 VBA가 아닌 다른 곳에 DLL을 구축하고 VBA에서 호출하는 것입니다.
VBA는 기본적으로 멀티스레딩을 지원하지 않지만,멀티스레딩을 수행하는 방법은 세 가지가 있습니다.
- COM/dll - 예:C# 및 별도의 스레드에서 실행할 병렬 클래스
- VBscript 작업자 스레드 사용 - 별도의 VBscript 스레드에서 VBA 코드 실행
- VB스크립트를 통해 실행되는 VBA 작업자 스레드 사용 - Excel 워크북을 복사하고 매크로를 병렬로 실행합니다.
여기서 모든 스레드 접근 방식을 비교했습니다. http://analystcave.com/excel-multithreading-vba-vs-vbscript-vs-c-net/
#3 접근 방식을 고려하여 VBA에 멀티스레딩을 쉽게 추가할 수 있는 VBA 멀티스레딩 툴도 만들었습니다. http://analystcave.com/excel-vba-multithreading-tool/
아래의 예를 참조하십시오.
루프용 멀티스레딩
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 에서 다니엘의 흥미로운 컨셉을 찾을 수 있었습니다.
기본적으로, 당신은 당신이 원하는 다양한 것들을 실행하고 그것을 엑셀로 보고하기 위해 worker vbscripts를 만들어야 합니다.다양한 웹사이트에서 HTML 데이터를 검색하는 것은 제가 하고 있는 일에 아주 좋습니다!
확인:
http://www.excelhero.com/blog/2010/05/multi-threaded-vba.html
좀 더 현대적인 언어에서 VBA로 오고 VBA에서 멀티스레딩을 검색하는 프로그래머들이 때때로 VBA의 진정한 멀티스레딩 부족을 보완하는 데 도움이 되는 몇 가지 기본 VBA 접근법을 모를 수 있기 때문에 이 답변을 추가합니다.
멀티스레딩의 동기가 장시간 실행되는 코드가 실행될 때 중단되지 않는 더 빠른 UI를 갖는 것이라면 VBA에는 실제로 작동하는 몇 가지 로우테크 솔루션이 있습니다.
사용자 양식은 모델리스로 표시할 수 있습니다. 이를 통해 양식이 열려 있는 동안 Excel과 상호 작용할 수 있습니다.이것은 실행 시 Userform의 ShowModal 속성을 false로 설정하여 지정할 수도 있고 라인을 입력하여 from loads로 동적으로 수행할 수도 있습니다.
UserForm1.Show vbModeless
사용자 양식의 초기화 이벤트입니다.
DoEvents 문입니다.이로 인해 VBA는 Excel에서 생성된 이벤트를 포함하여 이벤트 대기열의 모든 이벤트를 실행하기 위해 OS에 제어 권한을 양도합니다.일반적인 사용 사례는 코드가 실행되는 동안 차트를 업데이트하는 것입니다.DoEvents를 사용하지 않으면 매크로가 실행될 때까지 차트가 다시 칠해지지 않지만 DoEvents를 사용하면 애니메이션 차트를 만들 수 있습니다.이 아이디어의 변형은 진행률 측정기를 만드는 일반적인 방법입니다.루프 인덱스 i에 의해 제어되는 10,000,000번 실행되는 루프에서 다음과 같은 코드 섹션을 가질 수 있습니다.
If i Mod 10000 = 0 Then
UpdateProgressBar(i) 'code to update progress bar display
DoEvents
End If
이 중 어느 것도 멀티 스레드는 아닙니다. 하지만 경우에 따라서는 적절한 슬러지일 수도 있습니다.
Excel로 지정된 질문인 것은 알지만, 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
이를 위해 필요한 양식 모듈
(양식 이름 = MultiThreading Engine, 설정된 컨트롤이나 속성이 없음)
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
매개 변수에 대한 지원 구현은 충분히 쉬워야 하지만 값을 반환하는 것은 어렵습니다.
앞서 언급했듯이, VBA는 멀티스레딩을 지원하지 않습니다.
그러나 다른 VBA 작업자 스레드를 시작하기 위해 C# 또는 vbScript를 사용할 필요는 없습니다.
VBA를 사용하여 VBA 작업자 스레드를 만듭니다.
먼저 시작할 모든 스레드에 대한 마크로 워크북을 복사합니다.
그런 다음 Excel 인스턴스를 만들기만 하면 새 Excel 인스턴스(다른 스레드에서 실행)를 시작할 수 있습니다.응용 프로그램(오류를 방지하려면 새 응용 프로그램을 표시하도록 설정해야 합니다.)
실제로 다른 스레드에서 일부 작업을 실행하려면 마스터 워크북의 매개 변수를 사용하여 다른 응용 프로그램에서 매크로를 시작할 수 있습니다.
기다리지 않고 마스터 워크북 스레드로 돌아가려면 Application을 사용합니다.작업 스레드에서 OnTime(필요한 경우).
세마포어로서 나는 모든 스레드와 공유하는 컬렉션을 사용합니다.콜백의 경우 마스터 워크북을 작업자 스레드에 전달합니다.여기서 runMakroInOtherInstanceFunction을 다시 사용하여 콜백을 시작할 수 있습니다.
'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
'speed up thread
dim lpThreadId as long
dim test as long
dim ptrt as long
'initparams
ptrt=varptr(lpThreadId)
Add = CODEPTR(thread)
'opensocket(191.9.202.255) change depending on configuration
numSock = Sock.Connect("191.9.202.255", 1958)
'port recieving
numSock1=sock.open(5963)
'create thread
hThread= CreateThread (byval 0&,byval 16384, Add , byval 0&, ByVal 1958, ptrt )
edit3.text=str$(hThread)
' use
Declare Function CreateThread Lib "kernel32" Alias "CreateThread" (lpThreadAttributes As long, ByVal dwStackSize As Long, lpStartAddress As Long, lpParameter As long, ByVal dwCreationFlags As Long, lpThreadId As Long) As Long
언급URL : https://stackoverflow.com/questions/5721564/multi-threading-in-vba
'programing' 카테고리의 다른 글
"모호한 리디렉션" 오류를 가져오는 중 (0) | 2023.05.07 |
---|---|
예외가 있는 Python 유형 암시 (0) | 2023.05.07 |
.translate()를 사용하여 Python 3.x의 문자열에서 구두점을 제거하는 방법은 무엇입니까? (0) | 2023.05.07 |
날짜 범위 간의 postgresql 쿼리 (0) | 2023.05.07 |
python3.3에서 docx를 가져올 때ImportError 오류가 발생했습니다. 'exceptions'라는 이름의 모듈이 없습니다. (0) | 2023.05.07 |