Related
The script takes photos from the indicated folder and places them on slides according to the limit imposed by the user, e.g. 1000 photos / presentation. After that it has to create a new presentation.
It was working. But he stopped. Now I stop with a PowerPoint VBA error: "No currently active document window" at the moment when the script is to close the PowerPoint file and open a new one in which to continue saving the presentation.
Saving and closing a newly created presentation
Application.DisplayAlerts = ppAlertsNone
ActivePresentation.Save
ActiveWindow.Close <----- error here
Application.DisplayAlerts = ppAlertsAll
How to eliminate this error for the script to continue running?
All Code:
Option Explicit
Option Base 1
Option Private Module
Private il_plik As Integer
Private dostep_do_zdjec As Variant
Private tablica() As Variant
'Dla odwiedzających forum elektroda.pl - jeśli im się na coś przyda :)
Sub a_Dodaj_zdjecia_do_ppt()
Dim ogranicznik As Integer, roz_cznk_prw_str As Integer, roz_cznk_przezr As Integer
Dim plik As Integer, indeks As Integer, prezent As Integer, maks_zdj_prez As Integer
Dim maks_prez As Double
Dim cznk_prw_str As String, cznk_przezr As String, filterek As String, dostep_do_prez As String
Dim nazwa_prezent As String, nazwa_zdj As String, opis_zdj As String, prw_str As String
Dim opis_nagl_calej_prez As String, data_zdj As String, godzina_zdj As String
Dim info01 As String, info02 As String, info03 As String, info04 As String, info05 As String, info06 As String
Dim stempel_daty As Date
Dim il_zdj_w_prez As Variant
Dim nPrzezPrez As Object
'On Error GoTo koniec_blad
'-----------------------------------------------------------------------------------------------------------------------
'Ograniczenie maksymalnej ilości zdjęć na jedną prezentację
ogranicznik = 3000
'Ustawienia czcionki strony przewodniej - można sobie zmieniać poprzez tę zmienną
cznk_prw_str = "Arial" 'oryginalnie było "Calibri" - jednak ta czcionka z polskimi ą, ę, itd. nie wyświetlała się u mnie najlepiej
roz_cznk_prw_str = 36 '40
'Ustawienia czcionki strony przezrocza - można sobie zmieniać poprzez tę zmienną
cznk_przezr = "Arial" 'oryginalnie było "Calibri" - jednak ta czcionka z polskimi ą, ę, itd. nie wyświetlała się u mnie najlepiej
roz_cznk_przezr = 16 '18
'
'-----------------------------------------------------------------------------------------------------------------------
'
'Określenie opisu w nagłówku pojedynczej prezentacji - domyślne dla całej prezentacji
opis_nagl_calej_prez = Trim(InputBox("Proszę podać treść nagłówka dla przezroczy w prezentacji", "Treść nagłówka w prezentacji", "Zdjęcie wykonane w Kluczborku"))
'Określenie ilości zdjęć w pojedynczej prezentacji - domyślnie 500 szt.
il_zdj_w_prez = InputBox("Proszę podać ilość zdjęć na 1 prezentację", "Ilość zdjęć do umieszczenia w prezentacji", 500)
'Jeśli podano złą wartość
If il_zdj_w_prez = "" Or Not IsNumeric(Trim(il_zdj_w_prez)) Then
MsgBox "Podano złą wartość lub w ogóle jej nie podano" & vbCrLf & vbCrLf & "Koniec procedury", vbOKOnly + vbExclamation, "Uwaga !"
GoTo koniec
End If
'Jeśli podano dobrą wartość, ale w 'granicach przyzwoitości' typu Integer dla zmiennej 'ogranicznik'
il_zdj_w_prez = Abs(CInt(Trim(il_zdj_w_prez)))
If il_zdj_w_prez > ogranicznik Then
MsgBox "Przekroczono wartość graniczną" & vbCrLf & vbCrLf & "Koniec procedury", vbOKOnly + vbExclamation, "Uwaga !"
GoTo koniec
End If
'Określenie dostępu do katalogu ze zdjęciami
With Application.FileDialog(msoFileDialogFolderPicker)
filterek = ActivePresentation.Path
.AllowMultiSelect = False
.ButtonName = "Wybierz"
.InitialFileName = filterek
.Title = "Proszę wybrać katalog ze zdjęciami"
If .Show = -1 Then
dostep_do_zdjec = .SelectedItems(1)
Else
MsgBox "Nie podano dostępu do katalogu zdjęć" & vbCrLf & vbCrLf & "Koniec procedury", vbOKOnly + vbExclamation, "Uwaga !"
GoTo koniec
End If
End With
'Określenie dostępu do katalogu zapisywanych prezentacji
With Application.FileDialog(msoFileDialogFolderPicker)
filterek = ActivePresentation.Path
.AllowMultiSelect = False
.ButtonName = "Wybierz"
.InitialFileName = filterek
.Title = "Proszę podać miejsce zapisu prezentacji"
If .Show = -1 Then
dostep_do_prez = .SelectedItems(1)
Else
MsgBox "Nie podano dostępu do katalogu prezentacji" & vbCrLf & vbCrLf & "Koniec procedury", vbOKOnly + vbExclamation, "Uwaga !"
GoTo koniec
End If
End With
'Początek obróbki
MsgBox "Teraz rozpocznie się pobieranie nazw zdjęć" & vbCrLf & vbCrLf & "Może to trochę potrwać, zależnie od ich ilości", vbOKOnly, "Uwaga !"
'Pozyskanie nazw plików oraz ich posortowanie, wzrastająco, według daty utworzenia
'Pobrane zostaną tylko zdjęcia z rozszerzeniami: '*.bmp', '*.gif', '*.jpg', '*.jpeg', '*.png'
Call b_Lista_plikow_w_katalogu(dostep_do_zdjec)
Call c_sortowanie_babelkowe(tablica)
'Korekta liczby zdjęć w prezentacji, jeśli zadeklarowano większą ich ilość niż liczba wszystkich zdjęć do obróbki
If il_zdj_w_prez > il_plik Then il_zdj_w_prez = il_plik
'Określenie ilości prezentacji, jaka zostanie utworzona,
'w oparciu o ogólną ilość zdjęć i tych, przypadających na pojedynczą prezentację
maks_prez = (il_plik / il_zdj_w_prez) - Fix(il_plik / il_zdj_w_prez)
If maks_prez > 0 And maks_prez < 0.5 Then
maks_prez = Round(il_plik / il_zdj_w_prez, 0) + 1
Else
maks_prez = Round(il_plik / il_zdj_w_prez, 0)
End If
'Wartości początkowe zmiennych wyznaczających zakres 'od-do' zdjęć w prezentacji
maks_zdj_prez = il_zdj_w_prez
plik = 1
For prezent = 1 To maks_prez
'Utworzenie nazwy nowopowstającej prezentacji
Select Case prezent
Case Is <= 9: nazwa_prezent = "Prez_" & "000" & prezent & ".ppt"
Case Is <= 99: nazwa_prezent = "Prez_" & "00" & prezent & ".ppt"
Case Is <= 999: nazwa_prezent = "Prez_" & "0" & prezent & ".ppt"
Case Else: nazwa_prezent = "Prez_" & "" & prezent & ".ppt"
End Select
'Utworzenie i zapisanie na dysku nowopowstającej prezentacji - okno prezentacji widoczne - 'msoTrue'
Presentations.Add(WithWindow:=msoTrue).SaveAs dostep_do_prez & "\" & nazwa_prezent
'Zmiana wielkości okna programu
'ActiveWindow.View.Zoom = 75
'Wartość początkowa zmiennej ustalającej położenie danego przezrocza w prezentacji
indeks = 0
For plik = plik To maks_zdj_prez
'Wydzielenie nazwy kopiowanego zdjęcia oraz daty i godziny jego utworzenia
nazwa_zdj = Mid(tablica(plik), InStr(1, tablica(plik), ";", 1) + 1, Len(tablica(plik)) - InStr(1, tablica(plik), ";", 1))
stempel_daty = CDate(Mid(tablica(plik), 1, InStr(1, tablica(plik), ";", 1) - 1))
data_zdj = Format(stempel_daty, "dd.mm.yyyy")
godzina_zdj = Format(stempel_daty, "hh:mm")
'Zmienna na ewentualny, dodatkowy opis w nagłówku przezrocza pobrany z tablicy - tu niewykorzystana
opis_zdj = "Opis dodatkowy"
'Dodanie nowego przezrocza
indeks = indeks + 1
ActivePresentation.Slides.Add Index:=indeks, Layout:=ppLayoutBlank
'Przypisanie obiektu przezrocza do zmiennej - skrócenie zapisu obiektu
Set nPrzezPrez = ActivePresentation.Slides(indeks)
'Wkopiowanie zdjęcia
'LinkToFile:=msoFalse - teoretycznie uniezależnia wkopiowane zdjęcie od 'zdjęcia macierzystego' pobranego z katalogu
nPrzezPrez.Shapes.AddPicture FileName:=dostep_do_zdjec & "\" & nazwa_zdj, LinkToFile:=msoFalse, SaveWithDocument:=msoTrue, Left:=28, Top:=40, Width:=665, Height:=460
'Skalowanie wkopiowanego zdjęcia - zmianą liczby przy 'ScaleHeight' i 'ScaleWidth'
With nPrzezPrez.Shapes(1)
.LockAspectRatio = msoTrue
'.ScaleHeight 1.4, msoTrue, msoScaleFromMiddle 'msoScaleFromTopLeft 'msoScaleFromMiddle 'msoScaleFromBottomRight
'.ScaleWidth 1.4, msoTrue, msoScaleFromMiddle
.Width = 665
.Height = 460
End With
'Dodanie nagłówka
nPrzezPrez.Shapes.AddShape(msoShapeWave, 8.5, 9#, 703#, 62.38).TextFrame.TextRange.Text = "Zdjęcie nr " & Format(plik, "#,##0") & ": " & opis_nagl_calej_prez
'nPrzezPrez.Shapes.AddShape(msoShapeWave, 8.5, 9#, 703#, 62.38).TextFrame.TextRange.Text = "Zdjęcie nr " & Format(plik, "#,##0") & " (" & nazwa_zdj & ")"
'Inny układ opisu nagłówka - "Zdjęcie nr " & Format(plik, "#,##0") & ": " & nazwa_zdj & " - " & opis_zdj
'Formatowanie nagłówka
With nPrzezPrez.Shapes(2)
With .TextFrame
.AutoSize = ppAutoSizeNone
.WordWrap = msoFalse
With .TextRange
.ParagraphFormat.Alignment = ppAlignLeft
With .Font
.Name = cznk_przezr: .Size = roz_cznk_przezr: .Bold = msoTrue
.Color.RGB = RGB(0, 0, 0)
'.Color.SchemeColor = ppForeground
End With
End With
End With
With .Fill
.ForeColor.RGB = RGB(215, 228, 189)
.Solid
.Transparency = 0#
.Visible = msoTrue
End With
With .Line
.BackColor.RGB = RGB(255, 255, 255)
.ForeColor.RGB = RGB(79, 98, 40)
.Visible = msoTrue
End With
End With
'Dodanie stopki
nPrzezPrez.Shapes.AddShape(msoShapeWave, 8.5, 472#, 703#, 62.38).TextFrame.TextRange.Text = "DATA: " & data_zdj & ", godzina " & godzina_zdj
'Formatowanie stopki
With nPrzezPrez.Shapes(3)
With .TextFrame
.AutoSize = ppAutoSizeNone
.WordWrap = msoFalse
With .TextRange
.ParagraphFormat.Alignment = ppAlignLeft
With .Font
.Name = cznk_przezr: .Size = roz_cznk_przezr: .Bold = msoTrue
.Color.RGB = RGB(0, 0, 0)
'.Color.SchemeColor = ppForeground
End With
End With
End With
With .Fill
.ForeColor.RGB = RGB(215, 228, 189)
.Solid
.Transparency = 0#
.Visible = msoTrue
End With
With .Line
.BackColor.RGB = RGB(255, 255, 255)
.ForeColor.RGB = RGB(79, 98, 40)
.Visible = msoTrue
End With
End With
'Usunięcie dotychczasowych przypisań do zmiennych
Set nPrzezPrez = Nothing
nazwa_zdj = ""
stempel_daty = #1/1/1980#
data_zdj = ""
godzina_zdj = ""
opis_zdj = ""
'Co każde 1000 zdjęć 'odpuść' odrobinę na inne czynności - 'Niepraktyczne' w tym zadaniu
'If plik Mod 1000 = 0 Then DoEvents
Next plik
'Zmienna z tytułem prezentacji do strony przewodniej
prw_str = "PREZENTACJE" & vbCrLf & vbCrLf & "TYTUŁ" & vbCrLf & vbCrLf & "ILOŚĆ ZDJĘĆ: " & Format(indeks, "#,##0") & vbCrLf & vbCrLf & "OSTATNIA AKTUALIZACJA:" & vbCrLf & Format(Now(), "dd.mm.yyyy")
'Wstawienie strony przewodniej
ActivePresentation.Slides.Add Index:=1, Layout:=ppLayoutTitleOnly
'Sformatowanie strony przewodniej
With ActivePresentation.Slides(1).Shapes(1)
.Left = 54#
.Top = 167.75
.Width = 612.12
.Height = 115.62
With .TextFrame
.AutoSize = ppAutoSizeNone
.WordWrap = msoTrue
With .TextRange
.ParagraphFormat.Alignment = ppAlignCenter
.Text = prw_str
With .Font
.Name = cznk_prw_str: .Size = roz_cznk_prw_str
.Color.RGB = RGB(0, 0, 0)
'.Color.SchemeColor = ppForeground
End With
End With
End With
With .Fill
.Solid
.Transparency = 0#
.Visible = msoFalse
End With
With .Line
.Visible = msoFalse
End With
End With
'Zapis i zamknięcie nowoutworzonej prezentacji
Application.DisplayAlerts = ppAlertsNone
ActivePresentation.Save
' ActiveWindow.Close
ActivePresentation.Close
Application.DisplayAlerts = ppAlertsAll
'Czyszczenie zmiennej z tytułem prezentacji do strony przewodniej - na wszelki wypadek
prw_str = ""
'Jeśli przekroczono dopuszczalne wartości zmiennych, określone na początku, to korekta
'Można tu zastosować zmienną 'indeks'
maks_zdj_prez = il_zdj_w_prez + plik - 1
If maks_zdj_prez > il_plik Then maks_zdj_prez = il_plik
Next prezent
'Komunikat końcowy
info01 = "Procedura zakończona" & vbCrLf & vbCrLf
info02 = "Utworzono " & Format(maks_prez, "#,##0") & " prezentacje(-ę/-i) w: " & vbCrLf & vbCrLf
info03 = dostep_do_prez & vbCrLf & vbCrLf
info04 = "z " & Format(il_plik, "#,##0") & " zdjęć, po maksimum " & Format(il_zdj_w_prez, "#,##0") & " w każdej," & vbCrLf & vbCrLf
info05 = "pobranych z:" & vbCrLf & vbCrLf
info06 = dostep_do_zdjec
MsgBox info01 & info02 & info03 & info04 & info05 & info06, vbOKOnly, "Uwaga !"
Exit Sub
'Wykonaj jeśli w trakcie obróbki pojawił się jakiś błąd
koniec_blad:
On Error GoTo 0: On Error Resume Next
Application.DisplayAlerts = ppAlertsNone
With Presentations(nazwa_prezent)
.Saved = True: .Close
End With
Application.DisplayAlerts = ppAlertsAll
Set nPrzezPrez = Nothing
'Wykonaj po błędzie wyboru katalogu lub odwołaniu operacji ustalającej ilość zdjęć w prezentacji
koniec:
End
End Sub
Sub b_Lista_plikow_w_katalogu(dostep_do_zdjec As Variant)
Dim igt As Integer
Dim dlg As Integer, poz As Integer, licz As Integer
Dim rozsz_pliku As String
Dim ciag_prw As String, ciag_odtw As String, znak As String
Dim plik As Variant
Dim apli As Object, katalog As Object
On Error GoTo koniec
Set apli = CreateObject("Shell.Application")
Set katalog = apli.Namespace(dostep_do_zdjec)
'Inicjalizacja tablicy przechowującej dane o plikach zdjęć
ReDim tablica(1)
igt = 0
'Wpisanie informacji o plikach do tablicy
For Each plik In katalog.Items
'Wykonaj jeśli ma rozszerzenie
If InStrRev(plik, ".", -1, 1) <> 0 Then
rozsz_pliku = LCase(Mid(plik, InStrRev(plik, ".", -1, 1), 5))
'Pobierane będą dane tylko niektórych plików
If rozsz_pliku = ".jpg" Or rozsz_pliku = ".jpeg" Then
ciag_prw = CStr(katalog.GetDetailsOf(plik, 12))
'Dziwna wartość po wykonaniu <<katalog.GetDetailsOf(plik, 12)>>, tj. "?01-?03-?2017 ??19:21"
'Poniżej odtworzenie zapisu daty
dlg = Len(ciag_prw)
poz = 0
For licz = 1 To dlg
poz = poz + 1
znak = Mid(ciag_prw, poz, 1)
If Asc(znak) <> 63 Then ciag_odtw = ciag_odtw & znak
Next licz
If ciag_odtw = "" Then ciag_odtw = "01-01-1980 00:00"
igt = igt + 1
ReDim Preserve tablica(igt)
tablica(igt) = ciag_odtw & ";" & katalog.GetDetailsOf(plik, 0)
ciag_odtw = ""
Else
ciag_prw = CStr(katalog.GetDetailsOf(plik, 3))
If ciag_prw = "" Then ciag_prw = "01-01-1980 00:00"
igt = igt + 1
ReDim Preserve tablica(igt)
tablica(igt) = ciag_prw & ";" & katalog.GetDetailsOf(plik, 0)
ciag_prw = ""
End If
End If
Next plik
'Wstawia do zmiennej modułowej informację o ilości plików w tablicy
il_plik = igt
Set apli = Nothing
Set katalog = Nothing
Exit Sub
koniec:
Set apli = Nothing
Set katalog = Nothing
End Sub
Sub c_sortowanie_babelkowe(tablica As Variant)
Dim pocz As Integer, koniec As Integer
Dim i As Integer, j As Integer
Dim przech As Variant
On Error GoTo koniec
pocz = LBound(tablica)
koniec = UBound(tablica)
For i = pocz To koniec - 1
For j = i + 1 To koniec
If tablica(i) > tablica(j) Then
przech = tablica(j)
tablica(j) = tablica(i)
tablica(i) = przech
End If
Next j
Next i
Exit Sub
koniec:
End Sub
Edit://
I found a temporary solution to this. I fired this code, without the patch you wrote about on another computer, where I literally closed all windows in the window. Only the powerpoint was opened. The window with the script was on top. I didn't touch anything and the script worked fine on a large batch of photos (> 10k), creating a total of 11 presentation files. Can you explain to me as someone who is into programming and certainly VB programming does not know why this is happening and how to "remove" this problem?
I have created a file which I run multiple macros (for example 5). Everything works when I run all macros and I shared the file to a colleague (A) who said it works good. But when colleague (A) share to colleague (B), they encountered this error.
Can you please guide me on where I have been wrong?
Sub CaseListing()
Dim wbSource As Workbook, lastRow As Long
Application.ScreenUpdating = False
ThisWorkbook.Sheets("SR - Information").Range("A2:B1048576").Clear
Set wbSource = Workbooks.Open(Filename:="https://*/All_Region_Case_List_CURRENT.xlsx", UpdateLinks:=False, ReadOnly:=True)
lastRow = wbSource.Sheets("Sheet1").Range("B" & Rows.Count).End(xlUp).Row
wbSource.Activate
Range("B4:B" & lastRow & ",K4:K" & lastRow).Copy ThisWorkbook.Sheets("SR - Information").Range("A2")
wbSource.Close
With ThisWorkbook.Sheets("SR - Information").Range("A1:A" & Range("A" & Rows.Count).End(xlDown).Row)
.NumberFormat = "General"
.Value = .Value
End With
ThisWorkbook.Sheets("SR - Information").Range("E1") = "<-- last refreshed on " & Now()
Application.ScreenUpdating = True
End Sub
EMAIL
Public wsSR As Worksheet
Sub CreateEmail()
Dim TempFilePath As String, TempFileName As String, FileExtStr As String, myFile As String
Dim LastCell As Long, endR As Long
Dim Fname As String, Lname As String, EmailAddress As String
Dim ol As Outlook.Application
Dim mi As Outlook.MailItem
Dim c1, c2 As Collection, msg As String, i As Variant
Set wbMe = ThisWorkbook
Set wsBW = wbMe.Sheets("B+W")
Set wsSR = wbMe.Sheets("SR - Information")
Set wsFinal = wbMe.Sheets("Report")
Set wsCNA = ThisWorkbook.Sheets("C+N ")
Set wsWebCNA = ThisWorkbook.Sheets("Web")
Set c1 = New Collection
Set c2 = New Collection
pwd = "abc"
With Application
.ScreenUpdating = False
.EnableEvents = False
End With
wsFinal.Unprotect pwd
'Clear and Copy to the Final sheet
wsFinal.Range("A5:V1048576").Clear
LastCell = wsBW.Range("A" & Rows.Count).End(xlUp).Row
wsBW.Range("A4:V" & LastCell).Copy
wsFinal.Range("A4").PasteSpecial Paste:=xlPasteValues
Set wsSR = ThisWorkbook.Sheets("SR - Information")
endR = wsSR.Range("Q" & Rows.Count).End(xlUp).Row
wsSR.Visible = False
wsBW.Visible = False
wsCNA.Visible = False
wsWebCNA.Visible = False
wsFinal.Range("A4:V" & Cells(Rows.Count, 1).End(xlUp).Row).Columns.AutoFit
Set ol = New Outlook.Application
Set mi = ol.CreateItem(olMailItem)
For Each cel In Sheets("SR - Information").Range("Q2:Q" & endR).Cells
wsFinal.Activate
wsFinal.Unprotect pwd
Range("A4:V" & Cells(Rows.Count, 22).End(xlUp).Row).AutoFilter Field:=22, Criteria1:=cel ', visibledropdown:=False
Set IndxLookupRange = Sheets("SR - Information").Range("H:I")
Set Matchlookuprange = Sheets("SR - Information").Range("H:H")
cel.Offset(0, 1) = Application.WorksheetFunction.IfError(Application.Index(IndxLookupRange, Application.Match(cel, Matchlookuprange, 0), 2), "-")
EmailAddress = cel.Offset(0, 1)
'Temporary file details
TempFilePath = Environ$("temp") & "\"
TempFileName = " Report - " & Format(Now, "mmmm dd, yyyy")
FileExtStr = "." & LCase(Right(ThisWorkbook.Name, Len(ThisWorkbook.Name) - InStrRev(ThisWorkbook.Name, ".", , 1)))
If EmailAddress <> "-" Then
For Each oAccount In ol.Session.Accounts
If oAccount = "pqrs.abc#xyz.com" Then 'BD_Best_Practice
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0)
'Get the file ready - protection and hide
wsBW.protect pwd
wbMe.protect Password:=pwd, Structure:=True, Windows:=True
'Keep the desired sheet activate and save as temp file
wsFinal.Activate
wsFinal.protect pwd
wbMe.SaveCopyAs TempFilePath & TempFileName & FileExtStr
On Error Resume Next
With OutMail
.To = EmailAddress
.CC = ""
.BCC = ""
.Subject = " Report" '& Format(Now, "mmmm dd, yyyy") '" & Fname & "," & "<br> <br> "
.HTMLBody = "<BODY style='font-family:Calibri; font-size:11pt';>Hi, <br><br>" & _
"Please find the attached the Report. This report shows your Plan Sponsor's Enhanced Access user activity." & _
"<br> <br> Thank you, <br> xyz" & Range("F3") & "</font></BODY>"
.Attachments.Add TempFilePath & TempFileName & FileExtStr
Set .SendUsingAccount = oAccount
'.Display
.send
End With
On Error GoTo 0
Set OutMail = Nothing
Set OutApp = Nothing
End If
Next oAccount
'Delete the temp file
Kill TempFilePath & TempFileName & FileExtStr
Else
c1.Add cel, CStr(cel)
c2.Add cel, CStr(cel)
End If
Next cel
wbMe.Unprotect Password:=pwd
wsBW.Visible = True
wsSR.Visible = True
wsCNA.Visible = True
wsWebCNA.Visible = True
If c1.Count = 0 Then
msg = "All Service Reps are matched!"
Range("Q:R").Clear
MsgBox msg
Exit Sub
Else
msg = "Make sure to update the below list of Service Reps information manually!" & vbCrLf
For i = 1 To c1.Count
msg = msg & vbCrLf & c1.Item(i)
Next i
End If
MsgBox msg '& vbCrLf & vbCrLf & "Make sure Service Reps Details are updated manually!"
wsSR.Range("Q:R").Clear
wsBW.Select
With Application
.ScreenUpdating = True
.EnableEvents = True
End With
End Sub
IMPORTFILES
Public wbMe As Workbook
Public wsBW As Worksheet, wsSR As Worksheet, wsFinal As Worksheet
Public wsBoxi As Worksheet, wsWeb As Worksheet, wsWebCNA As Worksheet, wsNDR As Worksheet
Public pwd As Variant, domain As String
Public wsCNA As Worksheet
Sub ImportFiles()
'PURPOSE: 1 B and 1 W
Dim f, fpath As String
If MsgBox("Is it 2 B and 1 W?", vbYesNo) = vbNo Then
Set wbMe = ThisWorkbook
Set wsBW = wbMe.Sheets("B+W")
Set wsSR = wbMe.Sheets("SR - Information")
Set wsFinal = wbMe.Sheets("Report")
pwd = "abc"
Application.ScreenUpdating = False
wsBW.Unprotect pwd
If wsBW.AutoFilterMode = True Then wsBW.AutoFilterMode = False
wsBW.Range("A4:Y1048576").Clear
wbMe.Unprotect Password:=pwd ', Structure:=False, Windows:=False
wsSR.Visible = True
wsSR.Columns("P:R").Clear
P = wbMe.Sheets.Count
For m = P To 1 Step -1
t = wbMe.Sheets(m).Name
If t <> "B+W" And t <> "SR - Information" And t <> "Report" And t <> "C+ " And t <> "Web" And t <> "NDRs" Then
Application.DisplayAlerts = False
wbMe.Sheets(m).Delete
Application.DisplayAlerts = True
End If
Next m
fpath = GetFolder & "\"
Application.ScreenUpdating = False
If fpath = "\" Then
Exit Sub
Else
f = Dir(fpath)
Do While Len(f) > 0
Select Case Right(f, Len(f) - InStrRev(f, "."))
Case "xls", "xlsx", "csv"
OpenFile (fpath & f)
End Select
f = Dir
Loop
Set wsBoxi = wbMe.Sheets("Sheet1")
Set wsWeb = wbMe.Sheets("GBA Access IDS")
Call Merger
Call Reorder_Columns
'Apply Formats
wsWeb.Range("A1").Copy
wsBW.Range("A4:W4").PasteSpecial xlFormats
wsBW.Rows("4:4").Columns.AutoFit
Application.CutCopyMode = False
Range("A4").Select
P = wbMe.Sheets.Count
For m = P To 1 Step -1
t = wbMe.Sheets(m).Name
If t <> "BOXI+WEB" And t <> "SR - Information" And t <> "Report" And t <> "C+N " And t <> "Web" And t <> "NDRs" Then
Application.DisplayAlerts = False
wbMe.Sheets(m).Delete
Application.DisplayAlerts = True
End If
Next m
wsBW.Range("$A$4:$U$1048576").AutoFilter Field:=1, Criteria1:="C ", Operator:=xlOr, Criteria2:="N "
MsgBox "Merge Successful!"
Application.ScreenUpdating = True
End If
Else
Call LoopAllFilesInFolder
End If
End Sub
Function GetFolder() As String
Dim f As String
With Application.FileDialog(msoFileDialogFolderPicker)
.Title = "Select multiple Files"
.AllowMultiSelect = False
.InitialFileName = ThisWorkbook.Path
If .Show <> -1 Then GoTo There
f = .SelectedItems(1)
End With
There:
GetFolder = f
End Function
Private Sub OpenFile(filepath)
Dim sh, wb As Workbook
Set wb = Workbooks.Open(filepath)
'Debug.Print filepath
For Each sh In wb.Sheets
sh.Copy After:=wbMe.Sheets(wbMe.Sheets.Count)
Next sh
wb.Close False
End Sub
Private Sub Merger()
Dim lastRow As Long
wsBoxi.Rows("2:2").EntireRow.Delete
wsWeb.Rows("1:2").EntireRow.Delete
'Reorder BOXI columns
wsBoxi.Columns("D:D").Cut
wsBoxi.Columns("A:A").Insert Shift:=xlToRight
Set IndexRange = wsBoxi.Range("A:G") 'BOXI
Set MatchLookupRng = wsBoxi.Range("A:A")
lastRow = wsWeb.Range("A" & Rows.Count).End(xlUp).Row
wsWeb.Activate
For Each AdID In wsWeb.Range("E2:E" & lastRow).Cells
Range("P" & AdID.Row).Value = Application.IfError(Application.Index(IndexRange, Application.Match(AdID, MatchLookupRng, 0), 2), "-") 'Market Segment
Range("Q" & AdID.Row).Value = Application.IfError(Application.Index(IndexRange, Application.Match(AdID, MatchLookupRng, 0), 3), "-") 'Region code
Range("R" & AdID.Row).Value = Application.IfError(Application.Index(IndexRange, Application.Match(AdID, MatchLookupRng, 0), 4), "-") 'Cleint#
Range("S" & AdID.Row).Value = Application.IfError(Application.Index(IndexRange, Application.Match(AdID, MatchLookupRng, 0), 5), "-") 'Admin Access Level
Range("T" & AdID.Row).Value = Application.IfError(Application.Index(IndexRange, Application.Match(AdID, MatchLookupRng, 0), 6), "-") 'Admin Location Access
Range("U" & AdID.Row).Value = Application.IfError(Application.Index(IndexRange, Application.Match(AdID, MatchLookupRng, 0), 7), "-") 'Admin Access to all Locations
Next AdID
wsWeb.Range("P1").Value = "Market Segment"
wsWeb.Range("Q1").Value = "Region Code"
wsWeb.Range("R1").Value = "Client#"
wsWeb.Range("S1").Value = "Admin Access Level"
wsWeb.Range("T1").Value = "Admin Location Access"
wsWeb.Range("U1").Value = "Admin Access to all Locations"
wsWeb.Range("A1:U" & lastRow).Copy wsBW.Range("A4")
wsBW.Range("A4:Y1048576").Font.Name = "Calibri"
wsBW.Range("A4:Y1048576").Font.Size = 10
End Sub
Private Sub Reorder_Columns() 'Final Columns
Dim ColumnOrder As Variant, ndx As Integer
Dim Found As Range, counter As Integer
ColumnOrder = Array("Market Segment", "Region Code", "Requestor Access ID", "Requestor Email", "Client#", "Transaction Type", _
"Date Processed", "Admin First Name", "Admin Last Name", "Admin Language", "Admin Email", "Admin Access ID", "Admin Access Level", _
"Admin Location Access", "Admin Access to all Locations", "Changed Admin First Name", "Changed Admin Last Name", "Changed Admin Language", _
"Changed Admin Email", "Changed Admin Access Level", "Changed Admin Location Access")
counter = 1
wsBW.Activate
For ndx = LBound(ColumnOrder) To UBound(ColumnOrder)
Set Found = Rows("4:4").Find(ColumnOrder(ndx), LookIn:=xlValues, LookAt:=xlWhole, SearchOrder:=xlByColumns, SearchDirection:=xlNext, MatchCase:=False)
If Not Found Is Nothing Then
If Found.Column <> counter Then
Found.EntireColumn.Cut
Columns(counter).Insert Shift:=xlToRight
Application.CutCopyMode = False
End If
counter = counter + 1
End If
Next ndx
Call HighlightPlanAdmin
End Sub
Private Sub HighlightPlanAdmin()
Dim ReqID As Range, nReqID As String, rReqID As String, tType As String, ntType As String
wsBW.Activate
For Each ReqID In Range("C5:C" & Cells(Rows.Count, 1).End(xlUp).Row).Cells
rReqID = Trim(ReqID)
tType = Trim(ReqID.Offset(0, 3)) '"Add Plan Admin"
If tType = "Add Plan Admin" Then
nReqID = Trim(ReqID.Offset(1, 0)) 'Requestor ID next row
If rReqID = nReqID Then
ntType = Trim(ReqID.Offset(1, 3))
If ntType <> "Add Plan Admin to OASIS." Then
ReqID.Offset(0, 3).Font.ColorIndex = 3
End If
Else
ReqID.Offset(0, 3).Font.ColorIndex = 3
End If
If nReqID = "" Then
ntType = Trim(ReqID.Offset(1, 3))
If ntType = "" Then
ReqID.Offset(0, 3).Font.ColorIndex = 3
End If
End If
End If
Next ReqID
End Sub
Sub LoopAllFilesInFolder()
'PURPOSE: 2 B and 1 W. To loop through all Excel files in a user specified folder and perform ...
Application.ScreenUpdating = False
Application.DisplayAlerts = False
Set wsBW = ThisWorkbook.Sheets("B+W")
Set wsCNA = ThisWorkbook.Sheets("C+N ")
Set wsWebCNA = ThisWorkbook.Sheets("Web")
Set wsFinal = ThisWorkbook.Sheets("Report")
Set wsSR = ThisWorkbook.Sheets("SR - Information")
wsBW.Unprotect "abc"
If wsBW.AutoFilterMode = True Then wsBW.AutoFilterMode = False
wsSR.Range("Q1:R1048576").Clear
wsBW.Range("A4:Y1048576").Clear
wsCNA.Range("A1:G1048576").Clear
wsWebCNA.Range("A1:Z1048576").Clear
With Application.FileDialog(msoFileDialogFolderPicker)
.InitialFileName = Application.DefaultFilePath & "\"
.Title = "Select A Target Folder"
.Show
If .SelectedItems.Count <> 0 Then
xDirect = .SelectedItems(1) & "\"
xFname = Dir(xDirect, 7)
Do While xFname <> ""
If InStr(1, xFname, "C ", vbTextCompare) <> 0 Then
Set wb = Workbooks.Open(Filename:=xDirect & xFname)
dendRow = wsCNA.UsedRange.Rows.Count
wb.Worksheets(1).UsedRange.Copy
If dendRow = 1 Then
wsCNA.Range("A" & dendRow).PasteSpecial Paste:=xlPasteValues
Else
wsCNA.Range("A" & dendRow + 1).PasteSpecial Paste:=xlPasteValues
End If
wb.Close
ElseIf InStr(1, xFname, "N ", vbTextCompare) <> 0 Then
Set wb = Workbooks.Open(Filename:=xDirect & xFname)
dendRow = wsCNA.UsedRange.Rows.Count
wb.Worksheets(1).UsedRange.Copy
wsCNA.Range("A" & dendRow + 1).PasteSpecial Paste:=xlPasteValues
wb.Close
ElseIf InStr(1, xFname, "Web", vbTextCompare) <> 0 Then
Set wb = Workbooks.Open(Filename:=xDirect & xFname)
wb.Worksheets(1).UsedRange.Copy
wsWebCNA.Range("A1").PasteSpecial Paste:=xlPasteValues
wb.Close
End If
xFname = Dir
Loop
End If
End With
wsCNA.Activate
For Each cel In wsCNA.Range("A3:A" & Range("A" & Rows.Count).End(xlUp).Row).Cells
If InStr(1, cel, "Market Segment", vbTextCompare) <> 0 Then
cel.Offset(1, 0).EntireRow.Delete
cel.EntireRow.Delete
End If
Next cel
Call MergerFolder
Call Reorder_Columns_Folder
'Apply Formats
wsBW.Range("A4:W4").Font.Bold = True
wsBW.Range("A4:W4").Font.Underline = xlUnderlineStyleSingle
wsBW.Rows("4:4").Columns.AutoFit
Application.CutCopyMode = False
Range("A4").Select
wsBW.Range("$A$4:$U$1048576").AutoFilter Field:=1, Criteria1:="Corporate Accounts", Operator:=xlOr, Criteria2:="N "
MsgBox "Merge Successful!"
Application.ScreenUpdating = True
Application.DisplayAlerts = True
End Sub
Private Sub MergerFolder()
Dim lastRow As Long
wsCNA.Rows("2:2").EntireRow.Delete
wsWebCNA.Rows("1:2").EntireRow.Delete
'Reorder BOXI columns
wsCNA.Columns("D:D").Cut
wsCNA.Columns("A:A").Insert Shift:=xlToRight
Set IndexRange = wsCNA.Range("A:G") 'BOXI
Set MatchLookupRng = wsCNA.Range("A:A")
lastRow = wsWebCNA.Range("A" & Rows.Count).End(xlUp).Row
wsWebCNA.Activate
For Each AdID In wsWebCNA.Range("E2:E" & lastRow).Cells
Range("P" & AdID.Row).Value = Application.IfError(Application.Index(IndexRange, Application.Match(AdID, MatchLookupRng, 0), 2), "-") 'Market Segment
Range("Q" & AdID.Row).Value = Application.IfError(Application.Index(IndexRange, Application.Match(AdID, MatchLookupRng, 0), 3), "-") 'Region code
Range("R" & AdID.Row).Value = Application.IfError(Application.Index(IndexRange, Application.Match(AdID, MatchLookupRng, 0), 4), "-") 'Cleint#
Range("S" & AdID.Row).Value = Application.IfError(Application.Index(IndexRange, Application.Match(AdID, MatchLookupRng, 0), 5), "-") 'Admin Access Level
Range("T" & AdID.Row).Value = Application.IfError(Application.Index(IndexRange, Application.Match(AdID, MatchLookupRng, 0), 6), "-") 'Admin Location Access
Range("U" & AdID.Row).Value = Application.IfError(Application.Index(IndexRange, Application.Match(AdID, MatchLookupRng, 0), 7), "-") 'Admin Access to all Locations
Next AdID
wsWebCNA.Range("P1").Value = "Market Segment"
wsWebCNA.Range("Q1").Value = "Region Code"
wsWebCNA.Range("R1").Value = "Client#"
wsWebCNA.Range("S1").Value = "Admin Access Level"
wsWebCNA.Range("T1").Value = "Admin Location Access"
wsWebCNA.Range("U1").Value = "Admin Access to all Locations"
wsWebCNA.Range("A1:U" & lastRow).Copy wsBW.Range("A4")
wsBW.Range("A4:Y1048576").Font.Name = "Calibri"
wsBW.Range("A4:Y1048576").Font.Size = 10
End Sub
Private Sub Reorder_Columns_Folder() 'Final Columns
Dim ColumnOrder As Variant, ndx As Integer
Dim Found As Range, counter As Integer
ColumnOrder = Array("Market Segment", "Region Code", "Requestor Access ID", "Requestor Email", "Client#", "Transaction Type", _
"Date Processed", "Admin First Name", "Admin Last Name", "Admin Language", "Admin Email", "Admin Access ID", "Admin Access Level", _
"Admin Location Access", "Admin Access to all Locations", "Changed Admin First Name", "Changed Admin Last Name", "Changed Admin Language", _
"Changed Admin Email", "Changed Admin Access Level", "Changed Admin Location Access")
counter = 1
wsBW.Activate
For ndx = LBound(ColumnOrder) To UBound(ColumnOrder)
Set Found = Rows("4:4").Find(ColumnOrder(ndx), LookIn:=xlValues, LookAt:=xlWhole, SearchOrder:=xlByColumns, SearchDirection:=xlNext, MatchCase:=False)
If Not Found Is Nothing Then
If Found.Column <> counter Then
Found.EntireColumn.Cut
Columns(counter).Insert Shift:=xlToRight
Application.CutCopyMode = False
End If
counter = counter + 1
End If
Next ndx
Call HighlightPlanAdmin_Folder
End Sub
Private Sub HighlightPlanAdmin_Folder()
Dim ReqID As Range, nReqID As String, rReqID As String, tType As String, ntType As String
wsBW.Activate
For Each ReqID In Range("C5:C" & Cells(Rows.Count, 1).End(xlUp).Row).Cells
ReqID.Select
rReqID = Trim(ReqID)
tType = Trim(ReqID.Offset(0, 3)) '"Add Plan Admin"
If tType = "Add Plan Admin" Then
nReqID = Trim(ReqID.Offset(1, 0)) 'Requestor ID next row
If rReqID = nReqID Then
ntType = Trim(ReqID.Offset(1, 3))
If ntType <> "Add Plan Admin to OASIS." Then
ReqID.Offset(0, 3).Font.ColorIndex = 3
End If
Else
ReqID.Offset(0, 3).Font.ColorIndex = 3
End If
If nReqID = "" Then
ntType = Trim(ReqID.Offset(1, 3))
If ntType = "" Then
ReqID.Offset(0, 3).Font.ColorIndex = 3
End If
End If
End If
Next ReqID
End Sub
SRMATCH
Public wsSR As Worksheet
Sub ServiceRepMatch()
Set wsSR = ThisWorkbook.Sheets("SR - Information")
Set wsBW = ThisWorkbook.Sheets("B+W")
Set SRLookupRng = wsSR.Range("A:B")
Set macth = wsSR.Range("B1:B1048576")
Application.ScreenUpdating = False
wsBW.Range("V4").Value = "Service Reps"
For Each cel In wsBW.Range("E5:E" & Cells(Rows.Count, 1).End(xlUp).Row).Cells
cel.Offset(0, 17) = Application.IfError(Application.VLookup(cel, SRLookupRng, 2, 0), "-")
Next cel
wsBW.Range("V4:V" & Cells(Rows.Count, 22).End(xlUp).Row).Copy wsSR.Range("P1")
wsSR.Select
wsSR.Range("P1:P" & Cells(Rows.Count, 16).End(xlUp).Row).AdvancedFilter Action:=xlFilterCopy, CopyToRange:=wsSR.Range("Q1"), Unique:=True
wsSR.Columns("P").Clear
wsBW.Select
MsgBox "DONE!"
Application.ScreenUpdating = True
End Sub
In nutshell, we first run IMPORTFILES to merge 2 reports it can either be 2 or 3 and perform some data manipluations. Secondly, CASELISTING is used to get the SR's client#. Third, we match the respective sales representatives through SRMATCH. Last, we use CREATEEMAIL to send individual emails for SR's their report and confidently message in the Body.
I am trying to search for occurrences of a particular string in a Word document.
The code should search only after the Table of Contents.
My completed code is below:
Private Sub cmdFindNextAbbr_Click()
Dim myRange As range
'CREATING DICTONARY for Selected Items
If firstClickAbr = True Then
txtNew = ""
abSelIndex = 0
Set abSel = CreateObject("scripting.dictionary")
Set abSelFirstStart = CreateObject("scripting.dictionary")
firstClickAbr = False
iAbbr = 0
For x = 0 To lstAbbreviations.ListCount - 1
If lstAbbreviations.Selected(x) = True Then
If Not abSel.Exists(lstAbbreviations.List(x, 1)) Then
abSel.Add lstAbbreviations.List(x, 0), lstAbbreviations.List(x, 1)
abSelFirstStart.Add lstAbbreviations.List(x, 0), lstAbbreviations.List(x, 5)
End If
End If
Next x
End If
Dim Word, findText As String
Dim chkAbbrLast, fsCountExt, firstOccEnd As Integer
Do While abSelIndex < abSel.count
chkAbbrLast = 0
Set myRange = ActiveDocument.Content
If txtNew <> abSel.keys()(abSelIndex) Then
fnCountAbr = 0
locInteger = abbrTableEnd
End If
firstOccEnd = abSelFirstStart.items()(abSelIndex) + Len(abSel.items()(abSelIndex) & " (" & abSel.keys()(abSelIndex) & ")")
fnCountAbr = fnCountAbr + 1
Word = abSel.keys()(abSelIndex)
'initially search for full text
findText = abSel.items()(abSelIndex)
myRange.Start = locInteger
myRange.Find.ClearFormatting
Do While myRange.Find.Execute( _
findText:=findText, _
MatchCase:=False, _
MatchWholeWord:=True, _
Wrap:=wdFindStop, _
Forward:=True _
)
If Left(myRange.Style, 7) <> "Heading" Then
If abSelFirstStart.items()(abSelIndex) <> myRange.Start Then 'ignore the first occurrence
locInteger = myRange.End
tCount = tCount + 1
'check for full term and abbreviation
fsCountExt = Len(abSel.items()(abSelIndex) & "s (" & abSel.keys()(abSelIndex) & "s)")
myRange.End = myRange.Start + fsCountExt
If InStr(UCase(myRange.Text), UCase(abSel.items()(abSelIndex) & "s (" & abSel.keys()(abSelIndex) & "s)")) > 0 Then
txtNew = abSel.keys()(abSelIndex) & "s"
myRange.Select
Exit Sub
Else
fsCountExt = Len(abSel.items()(abSelIndex) & " (" & abSel.keys()(abSelIndex) & ")")
myRange.End = myRange.Start + fsCountExt
End If
If InStr(UCase(myRange.Text), UCase(abSel.items()(abSelIndex) & " (" & abSel.keys()(abSelIndex) & ")")) > 0 Then
txtNew = abSel.keys()(abSelIndex)
myRange.Select
Exit Sub
End If
'check for full term only
fsCountExt = Len(abSel.items()(abSelIndex) & "s (" & abSel.keys()(abSelIndex) & "s)")
myRange.End = myRange.Start + fsCountExt
If InStr(UCase(myRange.Text), UCase(abSel.items()(abSelIndex) & "s")) > 0 Then
txtNew = abSel.keys()(abSelIndex) & "s"
myRange.Select
Exit Sub
Else
fsCountExt = Len(abSel.items()(abSelIndex))
myRange.End = myRange.Start + fsCountExt
End If
If InStr(UCase(myRange.Text), UCase(abSel.items()(abSelIndex))) > 0 Then
txtNew = abSel.keys()(abSelIndex)
myRange.Select
Exit Sub
End If
End If
End If
chkAbbrLast = chkAbbrLast + 1 ' check to prevent infinite loop
myRange.End = ActiveDocument.Content.End
If chkAbbrLast > 2 Then
Exit Do
End If
Loop
'now search for abbreviation
findText = abSel.keys()(abSelIndex)
chkAbbrLast = 0
myRange.Start = locInteger
myRange.Find.ClearFormatting
Do While myRange.Find.Execute( _
findText:=findText, _
MatchCase:=True, _
MatchWholeWord:=True _
)
If Left(myRange.Style, 7) <> "Heading" And myRange.Start > firstOccEnd Then
If abbIgnoreList.contains(myRange.Start) Then ' skip if match is in ignore list
If abSelIndex = abSel.count - 1 Then
chkAbbrLast = chkAbbrLast + 1 ' check to prevent infinite loop
End If
locInteger = myRange.End
Else
locInteger = myRange.End
tCount = tCount + 1
fsCountExt = Len(abSel.keys()(abSelIndex) & "s")
myRange.End = myRange.Start + fsCountExt
If InStr(UCase(myRange.Text), UCase(abSel.keys()(abSelIndex) & "s")) > 0 Then
txtNew = abSel.keys()(abSelIndex) & "s"
myRange.Select
Exit Sub
Else
fsCountExt = Len(abSel.keys()(abSelIndex))
myRange.End = myRange.Start + fsCountExt
End If
If InStr(UCase(myRange.Text), UCase(abSel.keys()(abSelIndex))) > 0 Then
txtNew = abSel.keys()(abSelIndex)
myRange.Select
Exit Sub
End If
End If
End If
chkAbbrLast = chkAbbrLast + 1 ' check to prevent infinite loop
If chkAbbrLast > 2 Then
Exit Do
End If
myRange.End = ActiveDocument.Content.End
Loop
'loop to next/first item
If abSelIndex <= abSel.count - 1 Then
abSelIndex = abSelIndex + 1
Else
abSelIndex = 0 ' start again at beginning
End If
Loop
MsgBox "No further occurrences found"
End Sub
ToCEnd is 4085.
I am able to find the first result. When I click on a find next button, which calls the same method, I have the below values:
myRange.Start : 18046
myRange.End : 21467
However, after .Find.Execute, I have the below values:
myRange.Start : 18022
myRange.End : 18046
Why does the found text end at the start point I had defined earlier?
The difference between Start and End is the length of my string, 24
EDIT:
I have added the complete code.
What I am doing in the code is finding the text that the user may replace.
The replace is triggered from another button.
In the Find Next button event, I validate a result, store the end of the range to a variable and exit the sub.
On the next click, I am trying to search from the stored location onward.
I updated my code to be like the one at this link, still I have the same behavior.
You apparently want to loop through the found instances. For that you could use code like:
Sub Demo()
Application.ScreenUpdating = False
Dim i As Long
With ActiveDocument.Range
With .Find
.ClearFormatting
.Replacement.ClearFormatting
.Text = InputBox("What is the Text to Find")
.Replacement.Text = ""
.Forward = True
.Wrap = wdFindStop
.Format = False
.MatchCase = False
.MatchWholeWord = False
.MatchWildcards = False
.MatchSoundsLike = False
.MatchAllWordForms = False
.Execute
End With
Do While .Find.Found
i = i + 1
'insert code to do something with whatever's been found here
.Collapse wdCollapseEnd
.Find.Execute
Loop
End With
Application.ScreenUpdating = True
MsgBox i & " instances found."
End Sub
My macro in VBA Word 2016 (Win10) is verys slow for a 3-page document. What can I do to make it faster? Or is there another way I may count characters in paragraphs of different styles? I need to know how many characters are written in Normal style, H1-style etc.
Sub avsnittsteller()
'Optimize Code
Application.ScreenUpdating = False
'Rydd opp i formateringen
'Call stilFinner
intTittel = ActiveDocument.CustomDocumentProperties("malTittel").Value
intTittelI = ActiveDocument.CustomDocumentProperties("malTittelI").Value
intTittelX = ActiveDocument.CustomDocumentProperties("malTittelX").Value
intIngress = ActiveDocument.CustomDocumentProperties("malIngress").Value
intNormal = ActiveDocument.CustomDocumentProperties("malNormal").Value
'sett variablene til 0 før de avsnittene telles
Dim mlm(10) As String
tittel = 0
ingress = 0
mlm(1) = 0
mlm(2) = 0
mlm(3) = 0
mlm(4) = 0
mlm(5) = 0
mlm(6) = 0
mlm(7) = 0
' TELLE TEGN I ALLE AVSNITT
Dim Doc As Document
Set Doc = ActiveDocument
Dim para As Paragraph
Dim i As Long: i = 0
Dim j As Long: j = 0
Dim k As Long: k = 0
For Each para In Doc.Paragraphs
If para.Style = Doc.Styles("instruksjon") Or _
para.Style = Doc.Styles("Bildetekst") Or _
para.Style = Doc.Styles("Byline") Or _
para.Style = Doc.Styles("Byline email") Or _
para.Style = Doc.Styles("Fakta punkt") Or _
para.Style = Doc.Styles("tittel") Then
Else
If para.Style = Doc.Styles(wdStyleHeading1) Then
tittel = para.Range.Characters.Count - 1
Else
If para.Style = Doc.Styles(wdStyleHeading2) Then
ingress = para.Range.Characters.Count - 1
Else
If para.Style = Doc.Styles(wdStyleHeading3) Then
i = i + 1
mlm(i) = para.Range.Characters.Count - 1
Else
If para.Style = Doc.Styles(wdStyleNormal) Then
j = j + para.Range.Characters.Count - 1
End If 'N
End If 'H3
End If 'H2
End If 'H1
End If 'alle andre stiler
Next para
normal = j
'MsgBox "Tittelen din har " & tittel & " tegn" & vbCrLf & " ingress " & ingress & vbCrLf & " mlm-3 " & mlm(3) & vbCrLf & " mlm-4 " & mlm(4) & vbCrLf & "Alle normal " & normal
'MsgBox "Dokumentet blir nå lagret og antall tegn du har skrevet blir oppdatert øverst i dokumentet."
'MsgBox ActiveDocument.Paragraphs.Count
'DEFINER DOC PROPERTIES VARIABLENE
ActiveDocument.CustomDocumentProperties("tittel").Value = tittel
ActiveDocument.CustomDocumentProperties("ingress").Value = ingress
ActiveDocument.CustomDocumentProperties("mlm1").Value = mlm(1)
ActiveDocument.CustomDocumentProperties("mlm2").Value = mlm(2)
ActiveDocument.CustomDocumentProperties("mlm3").Value = mlm(3)
ActiveDocument.CustomDocumentProperties("mlm4").Value = mlm(4)
ActiveDocument.CustomDocumentProperties("mlm5").Value = mlm(5)
ActiveDocument.CustomDocumentProperties("mlm6").Value = mlm(6)
ActiveDocument.CustomDocumentProperties("mlm7").Value = mlm(7)
ActiveDocument.CustomDocumentProperties("normal").Value = j
ActiveDocument.Fields.Update 'OPPDATER ALLE FELT nb, virker ikke i bunn og topptekst
'MsgBox intTittelX
'Farg tittel og ingress rød om de er for lange, blå om de er passe korte
If tittel > intTittelX Then
With ActiveDocument.Styles(wdStyleHeading1).Font
.Color = wdColorRed
End With
Else
With ActiveDocument.Styles(wdStyleHeading1).Font
.Color = -738148353
End With
End If
If ingress > intIngress Then
With ActiveDocument.Styles(wdStyleHeading2).Font
.Color = wdColorRed
End With
Else
With ActiveDocument.Styles(wdStyleHeading2).Font
.Color = -738148353
End With
End If
'Optimize Code
Application.ScreenUpdating = True
End Sub
Try loading it into memory first, then taking action after the data has been loaded to an array. I just did a test with about 60 pages, it is taking about 8 seconds to populate the various attributes to an array. Once it's in the array, then manipulate it from there.
Here's the code:
Option Explicit
Public Sub test()
Debug.Print Now()
Dim doc As Document: Set doc = ActiveDocument
Dim i As Long
Dim myArr As Variant: ReDim myArr(1, 0 To doc.Paragraphs.Count - 1)
Dim para As Paragraph
For Each para In doc.Paragraphs
myArr(0, i) = para.Style
myArr(1, i) = para.Range.Characters.Count
i = i + 1
Next
Debug.Print Now()
Debug.Print myArr(0, 0), myArr(1, 0)
End Sub
I'm not sure if this is the proper way of doing this, but at least it works! I hope this code may help someone else looking for a way to loop through paragraphs and count the characters. Thank you Ryan!
Option Explicit
Public Sub avsnittsteller()
'http://stackoverflow.com/questions/42390551/vba-slow-macro-looping-through-paragraphs
Debug.Print Now()
Application.ScreenUpdating = True
'Rydd opp i formateringen
Call stilFinner
'deklarere variablene
Dim doc As Document: Set doc = ActiveDocument
Dim i As Long
Dim j As Long
Dim k As Long
Dim H1 As Long
Dim H2 As Long
Dim H3 As Long
Dim N As Long
Dim myArr As Variant: ReDim myArr(1, 0 To doc.Paragraphs.Count - 1)
Dim mlm(10) As String
Dim para As Paragraph
'Hent fram verdier i globale variabler som angir riktig lengde
intTittel = ActiveDocument.CustomDocumentProperties("malTittel").Value
intTittelI = ActiveDocument.CustomDocumentProperties("malTittelI").Value
intTittelX = ActiveDocument.CustomDocumentProperties("malTittelX").Value
intIngress = ActiveDocument.CustomDocumentProperties("malIngress").Value
intNormal = ActiveDocument.CustomDocumentProperties("malNormal").Value
'sett variablene til 0 før de avsnittene telles
tittel = 0
ingress = 0
mlm(1) = 0
mlm(2) = 0
mlm(3) = 0
mlm(4) = 0
mlm(5) = 0
mlm(6) = 0
mlm(7) = 0
'Lag en matrise (array) i minnet og kjør søket fra den
'Debug.Print doc.Paragraphs.Count
For Each para In doc.Paragraphs
myArr(0, i) = para.Style
myArr(1, i) = para.Range.Characters.Count - 1 'ComputeStatistics(wdStatisticCharacters)
i = i + 1
Next
'For hvert avsnitt fra 0 til antall avsnitt i dokumentet
For j = 0 To doc.Paragraphs.Count - 1
'Hvis avsnittets stil er Normal eller en av overskriftene så legg sammen alle tegnene
If myArr(0, j) = "Normal" Then
N = N + myArr(1, j)
'Debug.Print j, myArr(0, j), myArr(1, j)
End If
If myArr(0, j) = "Overskrift 1" Or myArr(0, j) = "Heading 1" Then
H1 = H1 + myArr(1, j)
'Debug.Print j, myArr(0, j), myArr(1, j)
End If
If myArr(0, j) = "Overskrift 2" Or myArr(0, j) = "Heading 2" Then
H2 = H2 + myArr(1, j)
'Debug.Print j, myArr(0, j), myArr(1, j)
End If
If myArr(0, j) = "Overskrift 3" Or myArr(0, j) = "Heading 3" Then
'Alle avsnitt med H3 telles ett og ett, summeres ikke
k = k + 1
mlm(k) = myArr(1, j)
Debug.Print j, myArr(0, j), myArr(1, j)
End If
Next j 'Neste avsnitt
'Debug.Print N & " " & H1 & " " & H2
'Debug.Print mlm(1) & " " & mlm(2) & " " & mlm(3) & " " & mlm(4) & " " & mlm(5)
'DEFINER DOC PROPERTIES VARIABLENE
ActiveDocument.CustomDocumentProperties("tittel").Value = H1
ActiveDocument.CustomDocumentProperties("ingress").Value = H2
ActiveDocument.CustomDocumentProperties("mlm1").Value = mlm(1)
ActiveDocument.CustomDocumentProperties("mlm2").Value = mlm(2)
ActiveDocument.CustomDocumentProperties("mlm3").Value = mlm(3)
ActiveDocument.CustomDocumentProperties("mlm4").Value = mlm(4)
ActiveDocument.CustomDocumentProperties("mlm5").Value = mlm(5)
ActiveDocument.CustomDocumentProperties("mlm6").Value = mlm(6)
ActiveDocument.CustomDocumentProperties("mlm7").Value = mlm(7)
ActiveDocument.CustomDocumentProperties("normal").Value = N
ActiveDocument.Fields.Update 'OPPDATER ALLE FELT nb, virker ikke i bunn og topptekst
'Farg tittel og ingress rød om de er for lange, blå om de er passe korte
If tittel > intTittelX Then
With ActiveDocument.Styles(wdStyleHeading1).Font
.Color = wdColorRed
End With
Else
With ActiveDocument.Styles(wdStyleHeading1).Font
.Color = -738148353
End With
End If
If ingress > intIngress Then
With ActiveDocument.Styles(wdStyleHeading2).Font
.Color = wdColorRed
End With
Else
With ActiveDocument.Styles(wdStyleHeading2).Font
.Color = -738148353
End With
End If
Application.ScreenUpdating = True
Debug.Print Now()
End Sub
I am experiencing some slowness problems is trying to refresh my datagrid with this code,
What I'm trying to do is manipulate the columns ACROSS variable (selltype_code).
objConn.Open()
Dim sqlConn As String = ("SELECT item_code, item_name, item_quantity, selltype_code, item_selldetail FROM qa_items")
Dim objDataAdapter As New MySqlDataAdapter(sqlConn, objConn)
Dim ds As New DataSet
objDataAdapter.Fill(ds, "items")
'Fill datagridview with FOR CICLE
For i As Int16 = 0 To ds.Tables("items").Rows.Count - 1
If ds.Tables("items").Rows(i).Item("selltype_code") = 1 Then
With Me.resultitems_seach_item
.Item(3, i).Style.ForeColor = ColorTranslator.FromOle(RGB(39, 74, 109)) 'Color para Precio
.Item(3, i).Value = ds.Tables("items").Rows(i).Item("item_selldetail") 'Valor para Precio
.Item(4, i).Style.ForeColor = Color.DarkGray
.Item(4, i).Value = "---"
.Item(5, i).Style.ForeColor = Color.DarkGray
.Item(5, i).Value = "---"
.Item(6, i).Style.ForeColor = Color.DarkGray
.Item(6, i).Value = "---"
End With
ElseIf ds.Tables("items").Rows(i).Item("selltype_code") = 2 Then
With Me.resultitems_seach_item
.Item(3, i).Style.ForeColor = Color.DarkGray
.Item(3, i).Value = "---"
.Item(4, i).Style.ForeColor = Color.DarkGray
.Item(4, i).Value = "---"
.Item(5, i).Style.ForeColor = ColorTranslator.FromOle(RGB(39, 74, 109)) 'Color para Precio
.Item(5, i).Value = ds.Tables("items").Rows(i).Item("item_selldetail")
.Item(6, i).Style.ForeColor = Color.DarkGray
.Item(6, i).Value = "---"
End With
ElseIf ds.Tables("items").Rows(i).Item("selltype_code") = 3 Then
With Me.resultitems_seach_item
.Item(3, i).Style.ForeColor = Color.DarkGray
.Item(3, i).Value = "---"
.Item(4, i).Style.ForeColor = ColorTranslator.FromOle(RGB(39, 74, 109)) 'Color para Precio
.Item(4, i).Value = ds.Tables("items").Rows(i).Item("item_selldetail")
.Item(5, i).Style.ForeColor = Color.DarkGray
.Item(5, i).Value = "---"
.Item(6, i).Style.ForeColor = Color.DarkGray
.Item(6, i).Value = "---"
End With
Else
With Me.resultitems_seach_item
.Item(3, i).Style.ForeColor = Color.DarkGray
.Item(3, i).Value = "---"
.Item(4, i).Style.ForeColor = Color.DarkGray
.Item(4, i).Value = "---"
.Item(5, i).Style.ForeColor = Color.DarkGray
.Item(5, i).Value = "---"
.Item(6, i).Style.ForeColor = ColorTranslator.FromOle(RGB(39, 74, 109)) 'Color para Precio
.Item(6, i).Value = ds.Tables("items").Rows(i).Item("item_selldetail")
End With
End If
Next i
objConn.Close()
Be sure you turn off any autoresize settings for grid columns. That slows down fetches considerably. Set the Grid AutoresizeMode to NONE before doing the refresh.