Problem whit VBA macros works in Office365 - vba
I faced with problem how macros works after start using Office365. In general macros should fill WORD template tags and bookmarks from txt data file. The problem is somtimes same data from data file doesn't past into template and there isn't any logics. It may be first,last, middele records of table. And more over most of times macros fill all data correctly. In Office2013/2016 all work properly.
Is there any ideas about this?
Macros code
Option Explicit
Type t_Ar
Col() As String
End Type
Dim isAutoOpen As String, _
WITHOUT_OLE As String, _
USE_JAR As String, _
UseUnicode As String, fs, f
Private Function GetFullPath(FullName As String) As String
Dim NameParts, Res As String, i As Integer
NameParts = Split(FullName, Application.PathSeparator)
Res = NameParts(0)
For i = 1 To UBound(NameParts) - 1
Res = Res + Application.PathSeparator + NameParts(i)
Next
GetFullPath = Res
End Function
Sub AutoOpen()
Dim FileNameData As String, FullPathMacros As String, ParsName, Cnt As Integer, _
AppMacros As Application, DocMacros As Document
'Stop
isAutoOpen = "X"
Set AppMacros = Application
Set DocMacros = AppMacros.ActiveDocument
'Mac косячит, вместо Path возвращает FullName
' FullPathMacros = Application.ActiveDocument.Path
FullPathMacros = GetFullPath(DocMacros.FullName)
ParsName = Split(DocMacros.Name, "_")
Cnt = UBound(ParsName)
If Cnt = 3 Then
If ParsName(0) = "ZWWW" And ParsName(1) = "MACROS" And ParsName(2) = "WORD" Then
If AppMacros.Documents.Count > 1 Then
' AppMacros.ActiveWindow.Visible = False
Else
AppMacros.Visible = False
End If
ParsName = Split(ParsName(3), ".")
FileNameData = FullPathMacros + AppMacros.PathSeparator + "ZWWW_DATA_" + ParsName(0) + ".txt"
FillVariables FileNameData, DocMacros
If WITHOUT_OLE = "X" Then
If AppMacros.Documents.Count > 1 Then
DocMacros.Close
Else
AppMacros.Quit
End If
End If
End If
End If
isAutoOpen = ""
End Sub
Private Function isFileUnicode(NameFileData As String) As Boolean
Dim b1 As Byte, b2 As Byte
isFileUnicode = False
On Error Resume Next
Open NameFileData For Random Access Read As #5 Len = 1
Get #5, 1, b1
Get #5, 2, b2
Close #5
If b1 = 0 Or b2 = 0 Then
isFileUnicode = True
End If
End Function
Private Sub OpenFileData(FileData As String)
Dim CodePageTxt As Integer
If UseUnicode <> "X" Then
Open FileData For Input As #1
Else
CodePageTxt = -2
If UseUnicode = "X" Then
CodePageTxt = -1
End If
Set fs = CreateObject("Scripting.FileSystemObject")
Set f = fs.OpenTextFile(FileData, 1, 0, CodePageTxt)
End If
End Sub
Private Sub CloseFileData()
If UseUnicode <> "X" Then
Close #1
Else
f.Close
End If
End Sub
Private Function isEndOfFileData() As Boolean
If UseUnicode <> "X" Then
isEndOfFileData = EOF(1)
Else
isEndOfFileData = f.AtEndOfStream
End If
End Function
Private Function ReadLineData() As String
Dim Ln As String
If UseUnicode <> "X" Then
Line Input #1, Ln
Else
Ln = f.ReadLine
End If
ReadLineData = Ln
End Function
Sub MakeFullDir(FullName As String)
Dim ArrName, NewDir As String, Cnt As Integer
ArrName = Split(FullName, Application.PathSeparator)
On Error Resume Next
Err.Clear
Cnt = 0
Do While Cnt < UBound(ArrName)
If NewDir = "" Then
NewDir = ArrName(Cnt)
Else
NewDir = NewDir + Application.PathSeparator + ArrName(Cnt)
End If
Err.Clear
ChDir NewDir
If Err.Number <> 0 Then
Err.Clear
MkDir NewDir
End If
Cnt = Cnt + 1
Loop
End Sub
Public Sub FillVariables(ByVal FileData As String, ByVal DocTempl) ' As Document
UserFormProgress.UserFormProgressShow FileData, DocTempl
End Sub
Public Sub ZWWW_FillVariables(ByVal FileData As String, ByVal DocTempl) ' As Document
Dim fs, f, _
Ln As String, r As Range, Ofs As Range, _
Ar() As t_Ar, i As Long, Cnt As Long, _
value, CurrRange As Range, _
RowsCount As Long, _
MACROSNAME, ErrNumber, VarError, _
Doc As Document, _
RangeStart, RangeEnd, RangeSize, _
NewStart, NewEnd, NewSize, _
RangeTempl, b As Bookmark, Dupl As Range, Fd As Find, _
CheckSpel, CheckGram, PasteAdjTblFormat As Boolean
' FileData As String
' QTable As QueryTable,
Dim Param, _
ProgressStep As Long, _
Psw As String, _
ResDialogPrint, _
TEMP_NAME As String, _
FILE_NAME As String, _
FILE_PATH As String, _
FULL_NAME As String, _
MACROS_NAME As String, _
DEBUG_MODE As String, _
CLOSE_FORM As String, _
PRINTDIALOG As String, _
PROTECT_WB As String, _
StartTime As Date, _
CurrentTime As Date
StartTime = Time * 100000
CurrentTime = StartTime
If isFileUnicode(FileData) Then
UseUnicode = "X"
Else
UseUnicode = ""
End If
RowsCount = 1
ErrNumber = 0
With Application
Set Doc = .ActiveDocument
.DisplayAlerts = wdAlertsNone
.ScreenUpdating = False
End With
With Options
CheckSpel = .CheckSpellingAsYouType
CheckGram = .CheckGrammarAsYouType
.CheckSpellingAsYouType = False
.CheckGrammarAsYouType = False
End With
OpenFileData FileData
Ln = ReadLineData()
Cnt = Ln
Do While Not isEndOfFileData() And Cnt > 0
Cnt = Cnt - 1
Ln = ReadLineData()
Param = Split(Ln, Chr(9))
If UBound(Param) = 1 Then
Select Case Param(0)
Case "TEMP_NAME"
TEMP_NAME = Param(1)
FULL_NAME = GetFullPath(Application.ActiveDocument.FullName) + Application.PathSeparator + TEMP_NAME
FULL_NAME = Replace(FULL_NAME, "\", Application.PathSeparator)
FULL_NAME = Replace(FULL_NAME, "/", Application.PathSeparator)
Case "FILE_NAME"
FILE_NAME = Param(1)
Case "FILE_PATH"
FILE_PATH = Param(1)
FILE_PATH = Replace(FILE_PATH, "\", Application.PathSeparator)
FILE_PATH = Replace(FILE_PATH, "/", Application.PathSeparator)
Case "WITHOUT_OLE"
WITHOUT_OLE = Param(1)
On Error Resume Next
Open Application.ActiveDocument.Path + Application.PathSeparator + Application.ActiveDocument.Name + ".err" For Input As #2
If Err.Number = 0 Then
WITHOUT_OLE = "X"
Close #2
Else
Err.Clear
End If
On Error GoTo 0
Case "USE_JAR"
USE_JAR = Param(1)
Case "MACROSNAME"
MACROS_NAME = Param(1)
Case "DEBUG_MODE"
DEBUG_MODE = Param(1)
Case "CLOSE_FORM"
CLOSE_FORM = Param(1)
Case "PRINTDIALOG"
PRINTDIALOG = Param(1)
Case "PROTECT"
PROTECT_WB = Param(1)
End Select
End If
Loop
If DEBUG_MODE = "X" Then
Application.Visible = True
Stop
End If
If isAutoOpen = "X" And WITHOUT_OLE = "" Then
CloseFileData
Exit Sub
End If
If (WITHOUT_OLE = "X" Or USE_JAR = "X") And FULL_NAME <> "" Then
' Dim App As New Word.Application
Dim App As Word.Application
If Left(UCase(Application.System.OperatingSystem), 7) = "WINDOWS" Then
Set App = New Application
Else
Set App = Application
End If
App.Documents.Open FULL_NAME
Set DocTempl = App.ActiveDocument
'сбросить Режим чтения в Word 2013,
'т.к. не заполняются колонтитулы
If DocTempl.ActiveWindow.View.ReadingLayout = True Then
'недостаточно сбросить Режим чтения,
'т.к. 2013 переводит в режим Черновик
DocTempl.ActiveWindow.View.Type = wdPrintView
End If
Else
Set App = DocTempl.Application
End If
DocTempl.Activate
Set Doc = App.ActiveDocument
PasteAdjTblFormat = App.Options.PasteAdjustTableFormatting
App.Options.PasteAdjustTableFormatting = False
If DEBUG_MODE = "X" Then
App.Visible = True
App.ScreenUpdating = True
Else
App.ScreenUpdating = False
App.DisplayAlerts = wdAlertsNone
End If
Cnt = 0
i = 0
Do While Not isEndOfFileData()
i = i + 1 'f.Line
Ln = ReadLineData()
ReDim Preserve Ar(1 To i) As t_Ar
Ar(i).Col = Split(Ln, Chr(9), 6, vbBinaryCompare)
Loop
CloseFileData
ProgressStep = UBound(Ar, 1) / 10
If ProgressStep > 50 Then
ProgressStep = 50
End If
If ProgressStep < 1 Then
ProgressStep = 1
End If
Err.Clear
ErrNumber = 0
Set r = Doc.Range
VarError = 0
i = 0
Do While Not i >= UBound(Ar, 1)
i = i + 1
App.ScreenUpdating = True
If DEBUG_MODE = "X" Then
App.ScreenUpdating = True
Else
App.ScreenUpdating = False
End If
'If i Mod ProgressStep = 0 Then
CurrentTime = Time * 100000 - StartTime
If CurrentTime > 1 Then
CurrentTime = Time * 100000
StartTime = CurrentTime
Dim ScrUpd As String
If DEBUG_MODE = "X" Then
ScrUpd = ", ScreenUpdating = "
If App.ScreenUpdating Then
ScrUpd = ScrUpd + "true"
Else
ScrUpd = ScrUpd + "false"
End If
End If
ProgressBar i, UBound(Ar, 1), FULL_NAME + ScrUpd
End If
With Ar(i)
' VarName = .Col(0)
' VarNum = .Col(1)
' FindText = .Col(2)
' Value = .Col(5)
' ErrNumber = 0
On Error Resume Next
If .Col(0) = "" Then
Set r = Doc.Range
ErrNumber = Err.Number
Else
If .Col(0) <> "*" Then
'At new VarName
Set b = Doc.Bookmarks(.Col(0))
Set r = b.Range
Set CurrRange = r.Duplicate
ErrNumber = Err.Number
If ErrNumber = 0 Then
r.Copy
'RowsCount = r.Rows.Count
RangeStart = r.Start
RangeEnd = r.End
RangeSize = RangeEnd - RangeStart
Doc.UndoClear
End If
If DEBUG_MODE = "X" Then
b.Select
r.Select
CurrRange.Select
End If
End If
If ErrNumber = 0 Then
If .Col(1) <> "*" Then
'At new VarNum
If .Col(1) <> 0 Then
r.Move 10, 1 'RowsCount
If DEBUG_MODE = "X" Then
r.Select
End If
If .Col(3) = "V" Then
Err.Clear
Set RangeTempl = Doc.Bookmarks(.Col(5)).Range
VarError = Err.Number
If DEBUG_MODE = "X" Then
RangeTempl.Select
End If
If VarError = 0 Then
NewStart = RangeTempl.Start
NewEnd = RangeTempl.End
RangeTempl.Copy
r.PasteAndFormat wdListCombineWithExistingList '(wdFormatOriginalFormatting)
NewSize = NewEnd - NewStart
NewStart = r.Start
NewEnd = NewStart + NewSize
r.End = NewEnd
If DEBUG_MODE = "X" Then
r.Select
End If
End If
Else
Set RangeTempl = CurrRange 'b.Range
RangeTempl.Copy
r.PasteAndFormat wdListCombineWithExistingList '(wdFormatOriginalFormatting)
b.Start = CurrRange.Start
b.End = CurrRange.End
NewStart = r.Start
NewEnd = NewStart + RangeSize
r.End = NewEnd
If DEBUG_MODE = "X" Then
r.Select
End If
End If
End If
Doc.UndoClear
End If
End If
End If
If ErrNumber = 0 Then
If .Col(2) = "" Then
If .Col(3) = "" Or .Col(3) = "S" Then
If DEBUG_MODE = "X" Then
r.Select
End If
r.Text = .Col(5)
ElseIf .Col(3) = "M" Then
Err.Clear
Set Dupl = r.Duplicate
If DEBUG_MODE = "X" Then
Dupl.Select
End If
'MacrosName = "'" + ActiveWorkbook.Name + "'" + "!" + .Col(5)
'MACROSNAME = .Col(5)
'App.Run MACROSNAME, Dupl
'If Err.Number <> 0 Then
' App.Run MACROSNAME
'End If
RunUserMacros App, .Col(5), Dupl
End If
Else
If .Col(3) = "S" Then
If DEBUG_MODE = "X" Then
r.Select
End If
Set Fd = r.Find
Fd.Execute FindText:=.Col(2), replacewith:=.Col(5), Replace:=wdReplaceAll
End If
End If
End If
End With
Err.Clear
Loop
Doc.UndoClear
i = 0
Do While Not i >= UBound(Ar, 1)
i = i + 1
With Ar(i)
If (.Col(0) <> "" And .Col(0) <> "*" And _
Val(.Col(1)) <> 0 And .Col(1) <> "*") Then
Err.Clear
Set b = Doc.Bookmarks(.Col(0))
If Err.Number = 0 Then
Set r = b.Range
If DEBUG_MODE = "X" Then
r.Select
End If
r.Delete
Set r = b.Range
If Err.Number = 0 Then
If DEBUG_MODE = "X" Then
r.Select
End If
r.Cells.Delete
End If
End If
End If
If .Col(3) = "V" Then
Err.Clear
Set b = Doc.Bookmarks(.Col(5))
If Err.Number = 0 Then
Set r = b.Range
If DEBUG_MODE = "X" Then
r.Select
End If
r.Delete
Set r = b.Range
If Err.Number = 0 Then
If DEBUG_MODE = "X" Then
r.Select
End If
r.Cells.Delete
End If
End If
ElseIf .Col(3) = "D" Then
Err.Clear
Set b = Doc.Bookmarks(.Col(0))
If Err.Number = 0 Then
Set r = b.Range
If DEBUG_MODE = "X" Then
r.Select
End If
r.Delete
Set r = b.Range
If Err.Number = 0 Then
If DEBUG_MODE = "X" Then
r.Select
End If
r.Cells.Delete
End If
End If
End If
End With
Loop
Doc.UndoClear
With App
.ScreenUpdating = True
.DisplayAlerts = wdAlertsAll
End With
With Options
.CheckSpellingAsYouType = CheckSpel
.CheckGrammarAsYouType = CheckGram
.PasteAdjustTableFormatting = PasteAdjTblFormat
End With
If WITHOUT_OLE = "X" Or USE_JAR = "X" Then
If PROTECT_WB = "X" Then
Err.Clear
Psw = Time
Doc.Protect Type:=3, noreset:=False, Password:=Psw
If Err.Number <> 0 Then
Err.Clear
Doc.Protect Type:=1, noreset:=False, Password:=Psw
End If
End If
Dim New_FULL_NAME As String, ErrSave, Saved_as_PDF As Boolean
New_FULL_NAME = FILE_PATH + FILE_NAME
If UCase(FULL_NAME) <> UCase(New_FULL_NAME) And FILE_NAME <> "" Then 'New_FULL_NAME <> ""
MakeFullDir New_FULL_NAME
If File_as_PDF(New_FULL_NAME) Then
Doc.Save
ErrSave = Save_as_PDF(Doc, New_FULL_NAME)
If ErrSave = 0 Then
Saved_as_PDF = True
End If
Else
Err.Clear
Doc.SaveAs FileName:=New_FULL_NAME
ErrSave = Err.Number
If ErrSave <> 0 Then
Doc.Save
End If
End If
Else
Doc.Save
End If
App.DisplayAlerts = True
App.ScreenUpdating = True
If CLOSE_FORM <> "X" Then
If Not Saved_as_PDF Then
With App
.DisplayAlerts = True
.ScreenUpdating = True
.Visible = True
End With
Else
Open_as_PDF New_FULL_NAME
End If
End If
If PRINTDIALOG = "X" Then
If Not Saved_as_PDF Then
ResDialogPrint = App.Dialogs.Item(wdDialogFilePrint).Show
End If
End If
If CLOSE_FORM = "X" Or _
PRINTDIALOG = "X" Or _
Saved_as_PDF Then
App.Quit
End If
End If
End Sub
Sub RunUserMacros(App, Val, Rng)
Dim MACROSNAME As String, Param1 As String, it_Params, Cnt As Integer
it_Params = Split(Val, Chr(9), 2, vbBinaryCompare)
Cnt = UBound(it_Params)
On Error Resume Next
Err.Clear
If Cnt >= 1 Then
MACROSNAME = it_Params(0)
Param1 = it_Params(1)
App.Run MACROSNAME, Rng, Param1
If Err.Number <> 0 Then
App.Run MACROSNAME, Param1
End If
Else
MACROSNAME = Val
App.Run MACROSNAME, Rng
If Err.Number <> 0 Then
App.Run MACROSNAME
End If
End If
Err.Clear
End Sub
Sub ProgressBar(LenPart, LenAll, Txt)
UserFormProgress.LabelText.Caption = Txt
UserFormProgress.LabelProgress.Width = (LenPart / LenAll) * UserFormProgress.FrameProgress.Width
' UserFormProgress.Show
UserFormProgress.Repaint
DoEvents
End Sub
Related
Need to slightly tweak this code...need it to find exact match and I'm out of my league
Public Function FindCodes(keywords As Range, text As String) 'FindCodes = "TEST" Dim codeRows As Collection Dim codeString As String Set codeRows = New Collection 'Find Codes For Each Item In keywords Dim keywordArr() As String Dim i As Integer i = 0 If Item.Row <> 1 Then 'Ignore first row keywordArr() = Split(Item, ",") 'On Error Resume Next On Error GoTo ErrHandler For Each s In keywordArr() If InStr(LCase(text), LCase(s)) <> 0 Then codeRows.Add Item.Row, CStr(Item.Row) End If Next s End If Next Item 'Build Codes String If codeRows.Count > 0 Then Dim codeArr() As String 'Set codeArr = New Collection 'Dim i As Integer 'i = 0 ReDim codeArr(codeRows.Count) For Each s In codeRows 'codeArr.Add s, CStr(Worksheets("Codes").Range("A" & s).Value) codeArr(i) = Worksheets("Codes").Range("A" & s).Value 'Set i = Worksheets("Codes").Range("B" + s).Value i = i + 1 Next s End If 'FindCodes = Join(codeArr, ",") If UBound(codeArr) > 1 Then FindCodes = Join(codeArr, ",") ElseIf UBound(codeArr) = 1 Then FindCodes = codeArr(0) Else FindCodes = "" End If ErrHandler: If Err.Number = 457 Or Err.Number = 0 Or Err.Number = 20 Then 'foo = someDefaultValue Resume Next Else 'Err.Raise Err.Number FindCodes = CVErr(xlErrValue) End If End Function Sub temp() Dim r As Range Set r = Worksheets("Codes").Range("B:B") MsgBox FindCodes(r, ".") End Sub
Your code seems over-complex, but maybe I'm misunderstanding what it's supposed to do. Try this: Public Function FindCodes(keywords As Range, text As String) Dim c As Range, keywordArr, s, rv 'only look at used cells Set keywords = Application.Intersect(keywords, keywords.Worksheet.UsedRange) For Each c In keywords.Cells If c.Row > 1 And Len(c.Value) > 0 Then 'Ignore first row and empty cells keywordArr = Split(c.Value, ",") For Each s In keywordArr If LCase(Trim(s)) = LCase(Trim(text)) Then 'grab value from ColA and go to next cell rv = rv & IIf(Len(rv) = 0, "", ",") & c.EntireRow.Cells(1).Value Exit For End If Next s End If Next c FindCodes = rv End Function
SlideShowWindows error (integer out of range)
I'm preparing a quiz using on PowerPoint using the controllers of VBA scripts. My aim to set multiple questions, each has 4 choices. I've set everything, when trying to run (starting with the method: "BeginQuiz") it's interrupted by the following error: SlideShowWindows (unknown number) Integer out of range My code is below: Const NOOFQS = 4 'Used to manipulated the unicode values of bulleted lists Const UD_CODE_1 = 111 Const UD_CODE_2 = 8226 Public QNo As Integer Public ExitFlag As Boolean Public Qs() As String Public Choices() As String Public Ans() As Integer Public UserAns() As Integer Sub NextSlide() ' Store the ans for later 'UserAns(QNo - 1) = 1 If QNo < NOOFQS Then QNo = QNo + 1 SlideShowWindows(1).Presentation.Slides("QSlide").Shapes(1).TextFrame.TextRange.Text = Qs(QNo - 1) AssignValues Else Call StopQuiz End If DoEvents End Sub Sub PreviousSlide() Static X As Integer If QNo > 1 Then QNo = QNo - 1 AssignValues End If End Sub Sub StopQuiz(Optional EndType As Boolean = False) ' EndType is used as a boolean Flag to indicate whether the user ran out of time ' or whether it was normal exit Dim ScoreCard As Integer Dim Ctr As Integer ExitFlag = True With SlideShowWindows(1) For Ctr = 0 To NOOFQS - 1 If Ans(Ctr) = UserAns(Ctr) Then ScoreCard = ScoreCard + 1 Next Ctr If EndType = False Then .Presentation.Slides("EndSlide").Shapes("Closing").TextFrame.TextRange.Text = "Your score is : " & ScoreCard & " correct out of " & NOOFQS Else .Presentation.Slides("EndSlide").Shapes("Closing").TextFrame.TextRange.Text = "Sorry!!! Either you ran out of time or you chickened out" _ & vbCrLf & "Better luck next time." & vbCrLf _ & "Your score is: " & ScoreCard & " correct out of " & NOOFQS End If .View.GotoSlide (.Presentation.Slides("EndSlide").SlideIndex) End With End Sub Sub StopIt() Call StopQuiz(True) End Sub Sub BeginQuiz() Dim Ctr As Integer ReDim Qs(NOOFQS) ReDim Ans(NOOFQS) ReDim UserAns(NOOFQS) ReDim Choices(NOOFQS, 4) ' All the questions Qs(0) = "1) ãä Ãæá ãä ÝÊÍ ÇáÞÏÓ ÈÚÏ ÚãÑ¿" Qs(1) = "2) ãä åí Ãæá ãä ÃÓáãÊ ãä ÇáäÓÇÁ¿" Qs(2) = "3) ãÇ åí ÇáãäØÞÉ ÇáÊí ÍÑÑåÇ ãÍãÏ ÇáÝÇÊÍ¿" Qs(3) = "4) ãÇ åæ Ãæá ãÓÌÏ Ýí ÇáÅÓáÇã¿" ' Set all user answers to negative For Ctr = 0 To NOOFQS - 1 UserAns(Ctr) = -1 Next Ctr ' All the choices 3 each for a question Choices(0, 0) = " ÕáÇÍ ÇáÏíä ÇáÃíæÈí" Choices(0, 1) = " ÇáÞÇÆÏ ÇáãÙÝÑ" Choices(0, 2) = " ÎÇáÏ Èä ÇáæáíÏ" Choices(0, 3) = " ÇáÙÇåÑ ÈíÈÑÓ" Choices(1, 0) = " ÃÓãÇÁ ÈäÊ ÃÈí ÈßÑ " Choices(1, 1) = " ÓæÏÉ ÈäÊ ÒãÚÉ " Choices(1, 2) = " ÎÏíÌÉ ÈäÊ ÎæíáÏ " Choices(1, 3) = " Ãã ÚãÇÑ Èä íÇÓÑ " Choices(2, 0) = " ØáíØáÉ " Choices(2, 1) = " ÇáÞÇÏÓíÉ " Choices(2, 2) = " ÇáÞÓØäØíäíÉ " Choices(2, 3) = " ÇáÃäÏáÓ" Choices(3, 0) = " ãÓÌÏ ÞÈÇÁ" Choices(3, 1) = " ãÓÌÏ Ðí ÇáäæÑíä" Choices(3, 2) = " ÇáãÓÌÏ ÇáäÈæí" Choices(3, 3) = " ÇáÈíÊ ÇáÍÑÇã" ' Provide the answer list here. ' Ans(0) = 0 means that the correct answer to the 1st question is the 1st choice. ' Ans(1) = 1 means that the correct answer to the 2nd question is the 2nd choice. ' Ans(2) = 1 means that the correct answer to the 3rd question is the 2nd choice. Ans(0) = 0 Ans(1) = 2 Ans(2) = 2 Ans(3) = 0 QNo = 1 AssignValues With SlideShowWindows(1) .View.GotoSlide (.Presentation.Slides("QSlide").SlideIndex) End With ' Comment the line below to stop the timer. Call Tmr End Sub Sub SetBulletUnicode(ShapeName As String, Code As Integer) With SlideShowWindows(1).Presentation.Slides("QSlide").Shapes(ShapeName).TextFrame.TextRange.ParagraphFormat.Bullet .UseTextFont = msoTrue .Character = Code End With End Sub Sub ButtonChoice1() UserAns(QNo - 1) = 0 AssignValues End Sub Sub ButtonChoice2() UserAns(QNo - 1) = 1 AssignValues End Sub Sub ButtonChoice3() UserAns(QNo - 1) = 2 AssignValues End Sub Sub Tmr() 'Just in the eventuality that you click the start button twice 'isRunning stores the current state of the macro 'TRUE = Running; FALSE = Idle ExitFlag = False Static isRunning As Boolean If isRunning = True Then End Else isRunning = True Dim TMinus As Integer Dim xtime As Date xtime = Now With ActivePresentation.Slides(2).Shapes("Timer") 'Countdown in seconds TMinus = 59 Do While (TMinus > -1) DoEvents ' Rather crude way to determine if a second has elapsed If ExitFlag = True Then .TextFrame.TextRange.Text = "00:00:00" isRunning = False Exit Sub End If If Format(Now, "ss") <> Format(xtime, "ss") Then xtime = Now .TextFrame.TextRange.Text = Format(TimeValue(Format(Now, "hh:mm:ss")) - _ TimeSerial(Hour(Now), Minute(Now), Second(Now) + TMinus), "hh:mm:ss") TMinus = TMinus - 1 ' Let the display refresh itself End If Loop End With Debug.Print "came here" isRunning = False StopQuiz True End End If End Sub Sub AssignValues() SetBulletUnicode "Choice1", UD_CODE_1 SetBulletUnicode "Choice2", UD_CODE_1 SetBulletUnicode "Choice3", UD_CODE_1 SetBulletUnicode "Choice4", UD_CODE_1 Select Case UserAns(QNo - 1) Case 0 SetBulletUnicode "Choice1", UD_CODE_2 Case 1 SetBulletUnicode "Choice2", UD_CODE_2 Case 2 SetBulletUnicode "Choice3", UD_CODE_2 Case 3 SetBulletUnicode "Choice4", UD_CODE_2 End Select With SlideShowWindows(1).Presentation.Slides("QSlide") .Shapes(1).TextFrame.TextRange.Text = Qs(QNo - 1) .Shapes("Choice1").TextFrame.TextRange.Text = Choices(QNo - 1, 0) .Shapes("Choice2").TextFrame.TextRange.Text = Choices(QNo - 1, 1) .Shapes("Choice3").TextFrame.TextRange.Text = Choices(QNo - 1, 2) .Shapes("Choice4").TextFrame.TextRange.Text = Choices(QNo - 1, 3) End With End Sub Sub ShowAnswers() Dim AnsList As String AnsList = "The answers are as follows:" & vbCrLf For X = 0 To NOOFQS - 1 AnsList = AnsList & Qs(X) & vbTab & " Answer:" & Choices(X, Ans(X)) & vbCrLf Next X MsgBox AnsList, vbOKOnly, "Correct answers" End Sub
VBA loop for label names
I have a Word table containing Legacy DropDown List. There is 11 rows and let's say 4 columns. Each cell contains a Legacy DropDown List which puts the count to 11 per column (44 total). I have to take the data from these Legacy DropDown List and put it into Labels in another table on another page of the same document. No problem so far, I made it work though I had to do write it all down instead of using a loop because I couldn't find a way to put a variable in my label name. I shortened my code to only the first row of the first week (therefore 4 labels) because otherwise it would have been too long and there is no need for it to be that way. Current code : Sub Week1() 'Week 1 If ActiveDocument.FormFields("Dom1").DropDown.ListEntries.Count <> 0 And ActiveDocument.FormFields("Dom1").DropDown.ListEntries.Item(ActiveDocument.FormFields("Dom1").DropDown.Value).Name <> "Choose a DOM." Then lblDom1W1.Caption = ActiveDocument.FormFields("Dom1").DropDown.ListEntries.Item(ActiveDocument.FormFields("Dom1").DropDown.Value).Name End If If ActiveDocument.FormFields("Sit1").DropDown.ListEntries.Count <> 0 Then If ActiveDocument.FormFields("Sit1").DropDown.Value <> 0 Then If ActiveDocument.FormFields("Sit1").DropDown.ListEntries.Item(ActiveDocument.FormFields("Sit1").DropDown.Value).Name <> "Choose a SIT" Then lblSit1W1.Caption = ActiveDocument.FormFields("Sit1").DropDown.ListEntries.Item(ActiveDocument.FormFields("Sit1").DropDown.Value).Name End If End If End If If ActiveDocument.FormFields("Int1").DropDown.ListEntries.Count <> 0 Then If ActiveDocument.FormFields("Int1").DropDown.Value <> 0 Then lblInt1W1.Caption = ActiveDocument.FormFields("Int1").DropDown.ListEntries.Item(ActiveDocument.FormFields("Int1").DropDown.Value).Name End If End If If ActiveDocument.FormFields("Gram1").DropDown.ListEntries.Count <> 0 And ActiveDocument.FormFields("Gram1").DropDown.ListEntries.Item(ActiveDocument.FormFields("Gram1").DropDown.Value).Name <> "Choose a GRAM." Then lblGram1W1.Caption = ActiveDocument.FormFields("Gram1").DropDown.ListEntries.Item(ActiveDocument.FormFields("Gram1").DropDown.Value).Name End If So this works. That being said, I would like to loop it so I could have this much code only once instead of having it repeated 11 times per week for 11 weeks. I already named the labels for them to be easy with a loop. Therefore, their names are all lblDom1W1 down to lblDom11W1 for the first week and so on for the other labels (only the last digit changes ( e.i. lblDom1W2 down to lblDom11W2)). Furthermore, I thought and tried these methods which I thought wouldn't work and didn't : labelName & value labelName(value) I looked through this post but I didn't quite understood everything in it and I'm not sure if that's what I need since it's VB.NET and no exactly VBA. Post I checked EDIT: Following user R3uK comment, I tried this but it doesn't work either. I gives me the Invalid qualifier for my leLabelDom.Caption...: Sub Week1() 'Week1 Dim labelDom As String labelDom = "lblDom" Dim week1 As String week1 = "W1" Dim leLabelDom As String For k = 1 To 11 leLabelDom = labelDom & k & week1 If ActiveDocument.FormFields("ListeDomaine" & k).DropDown.ListEntries.Count <> 0 And ActiveDocument.FormFields("ListeDomaine" & k).DropDown.ListEntries.Item(ActiveDocument.FormFields("ListeDomaine" & k).DropDown.Value).Name <> "Choisissez un domaine." Then leLabelDom.Caption = ActiveDocument.FormFields("ListeDomaine" & k).DropDown.ListEntries.Item(ActiveDocument.FormFields("ListeDomaine" & k).DropDown.Value).Name End If EDIT 2 - Working: Started from the user R3uK answer and end up with this code which works. Huge thanks to you R3uK ! Sub Remplir() Dim leLabelDom As String, _ wDocD As Word.Document, _ IsHd As InlineShape, _ leLabelSit As String, _ leLabelInt As String, _ leLabelGram As String, _ semaine As String Set wDoc = ActiveDocument If ActiveDocument.FormFields("ListeSemaine").DropDown.ListEntries.Item(ActiveDocument.FormFields("ListeSemaine").DropDown.Value).Name = "Semaine 1" Then semaine = "S1" lblMaterielS1.Caption = TextBoxMateriel.Text lblEvaluationS1.Caption = TextBoxEvaluation.Text End If If ActiveDocument.FormFields("ListeSemaine").DropDown.ListEntries.Item(ActiveDocument.FormFields("ListeSemaine").DropDown.Value).Name = "Semaine 2" Then semaine = "S2" lblMaterielS2.Caption = TextBoxMateriel.Text lblEvaluationS2.Caption = TextBoxEvaluation.Text End If If ActiveDocument.FormFields("ListeSemaine").DropDown.ListEntries.Item(ActiveDocument.FormFields("ListeSemaine").DropDown.Value).Name = "Semaine 3" Then semaine = "S3" lblMaterielS3.Caption = TextBoxMateriel.Text lblEvaluationS3.Caption = TextBoxEvaluation.Text End If If ActiveDocument.FormFields("ListeSemaine").DropDown.ListEntries.Item(ActiveDocument.FormFields("ListeSemaine").DropDown.Value).Name = "Semaine 4" Then semaine = "S4" lblMaterielS4.Caption = TextBoxMateriel.Text lblEvaluationS4.Caption = TextBoxEvaluation.Text End If If ActiveDocument.FormFields("ListeSemaine").DropDown.ListEntries.Item(ActiveDocument.FormFields("ListeSemaine").DropDown.Value).Name = "Semaine 5" Then semaine = "S5" lblMaterielS5.Caption = TextBoxMateriel.Text lblEvaluationS5.Caption = TextBoxEvaluation.Text End If If ActiveDocument.FormFields("ListeSemaine").DropDown.ListEntries.Item(ActiveDocument.FormFields("ListeSemaine").DropDown.Value).Name = "Semaine 6" Then semaine = "S6" lblMaterielS6.Caption = TextBoxMateriel.Text lblEvaluationS6.Caption = TextBoxEvaluation.Text End If If ActiveDocument.FormFields("ListeSemaine").DropDown.ListEntries.Item(ActiveDocument.FormFields("ListeSemaine").DropDown.Value).Name = "Semaine 7" Then semaine = "S7" lblMaterielS7.Caption = TextBoxMateriel.Text lblEvaluationS7.Caption = TextBoxEvaluation.Text End If If ActiveDocument.FormFields("ListeSemaine").DropDown.ListEntries.Item(ActiveDocument.FormFields("ListeSemaine").DropDown.Value).Name = "Semaine 8" Then semaine = "S8" lblMaterielS8.Caption = TextBoxMateriel.Text lblEvaluationS8.Caption = TextBoxEvaluation.Text End If If ActiveDocument.FormFields("ListeSemaine").DropDown.ListEntries.Item(ActiveDocument.FormFields("ListeSemaine").DropDown.Value).Name = "Semaine 9" Then semaine = "S9" lblMaterielS9.Caption = TextBoxMateriel.Text lblEvaluationS9.Caption = TextBoxEvaluation.Text End If If ActiveDocument.FormFields("ListeSemaine").DropDown.ListEntries.Item(ActiveDocument.FormFields("ListeSemaine").DropDown.Value).Name = "Semaine 10" Then semaine = "S10" lblMaterielS10.Caption = TextBoxMateriel.Text lblEvaluationS10.Caption = TextBoxEvaluation.Text End If If ActiveDocument.FormFields("ListeSemaine").DropDown.ListEntries.Item(ActiveDocument.FormFields("ListeSemaine").DropDown.Value).Name = "Semaine 11" Then semaine = "S11" lblMaterielS11.Caption = TextBoxMateriel.Text lblEvaluationS11.Caption = TextBoxEvaluation.Text End If For k = 1 To 11 leLabelDom = "lblDomaine" & k & semaine leLabelSit = "lblSituation" & k & semaine leLabelInt = "lblIntention" & k & semaine leLabelGram = "lblGrammaire" & k & semaine If wDoc.FormFields("ListeDomaine" & k).DropDown.ListEntries.Count <> 0 And _ wDoc.FormFields("ListeDomaine" & k).DropDown.ListEntries.Item(wDoc.FormFields("ListeDomaine" & k).DropDown.Value).Name <> "Choisissez un domaine." _ Then If wDoc.InlineShapes.Count <> 0 Then For Each IsH In wDoc.InlineShapes If IsH.Type = wdInlineShapeOLEControlObject Then If TypeName(IsH.OLEFormat.Object) = "Label" Then If IsH.OLEFormat.Object.Name = leLabelDom Then IsH.OLEFormat.Object.Caption = wDoc.FormFields("ListeDomaine" & k).DropDown.ListEntries.Item(wDoc.FormFields("ListeDomaine" & k).DropDown.Value).Name End If End If End If Next End If End If If wDoc.FormFields("ListeSituation" & k).DropDown.ListEntries.Count <> 0 _ Then If wDoc.FormFields("ListeSituation" & k).DropDown.Value <> 0 _ Then If wDoc.FormFields("ListeSituation" & k).DropDown.ListEntries.Item(wDoc.FormFields("ListeSituation" & k).DropDown.Value).Name <> "Choisissez une situation" _ Then If wDoc.InlineShapes.Count <> 0 Then For Each IsH In wDoc.InlineShapes If IsH.Type = wdInlineShapeOLEControlObject Then If TypeName(IsH.OLEFormat.Object) = "Label" Then If IsH.OLEFormat.Object.Name = leLabelSit Then IsH.OLEFormat.Object.Caption = wDoc.FormFields("ListeSituation" & k).DropDown.ListEntries.Item(wDoc.FormFields("ListeSituation" & k).DropDown.Value).Name End If End If End If Next End If End If End If End If If wDoc.FormFields("ListeIntention" & k).DropDown.ListEntries.Count <> 0 And _ wDoc.FormFields("ListeIntention" & k).DropDown.Value <> 0 _ Then If wDoc.InlineShapes.Count <> 0 Then For Each IsH In wDoc.InlineShapes If IsH.Type = wdInlineShapeOLEControlObject Then If TypeName(IsH.OLEFormat.Object) = "Label" Then If IsH.OLEFormat.Object.Name = leLabelInt Then IsH.OLEFormat.Object.Caption = wDoc.FormFields("ListeIntention" & k).DropDown.ListEntries.Item(wDoc.FormFields("ListeIntention" & k).DropDown.Value).Name End If End If End If Next End If End If If wDoc.FormFields("ListeGrammaire" & k).DropDown.ListEntries.Count <> 0 And _ wDoc.FormFields("ListeGrammaire" & k).DropDown.ListEntries.Item(wDoc.FormFields("ListeGrammaire" & k).DropDown.Value).Name <> "Choisissez un niveau." _ Then If wDoc.InlineShapes.Count <> 0 Then For Each IsH In wDoc.InlineShapes If IsH.Type = wdInlineShapeOLEControlObject Then If TypeName(IsH.OLEFormat.Object) = "Label" Then If IsH.OLEFormat.Object.Name = leLabelGram Then IsH.OLEFormat.Object.Caption = wDoc.FormFields("ListeGrammaire" & k).DropDown.ListEntries.Item(wDoc.FormFields("ListeGrammaire" & k).DropDown.Value).Name End If End If End If Next End If End If Next k Set wDoc = Nothing End Sub
In your edit, you try to use a property for a String, but Properties are only for Object variables. So, you need to find where are stored the controls, in InlineShapes and then loop and filter it to narrow it down to your specific control and change its value. Here is something that should work or at least is probably close (can't test it) : Sub OuO() Dim leLabelDom As String, _ wDoc As Word.Document, _ wListE As DropDown, _ IsH As InlineShape Set wDoc = wDoc For k = 1 To 11 leLabelDom = "lblDom" & k & "W1" Set wListE = wDoc.FormFields("ListeDomaine" & k).DropDown If wListE.ListEntries.Count <> 0 And _ wListE.ListEntries.Item(wListE.Value).Name <> "Choisissez un domaine." _ Then If wDoc.InlineShapes.Count <> 0 Then For Each IsH In wDoc.InlineShapes If IsH.Type <> wdInlineShapeOLEControlObject Then Else 'filter on name With IsH.OLEFormat.Object If .Name <> leLabelDom Then Else .Caption = wListE.ListEntries.Item(wListE.Value).Name End If End With End If Next IsH Else End If Else End If Next k Set wDoc = Nothing Set wListE = Nothing End Sub
Do Until loop in VBA does not break on Exit Sub
I wrote the following code in order to ask for an input. validInput = False Do str = InputBox("Some text...") If str = vbNullString Then MsgBox ("Input canceled") Exit Sub Else If IsNumeric(str) Then exchange = CCur(str) validInput = True Else MsgBox ("Input invalid.") End If End If Loop Until validInput However, if I cancel my input it keeps asking me for an input and the loop goes on even though I added the Exit Sub line. I tried to add validInput = True before Exit Sub but that didn't work either. What am I missing? EDIT: Here is the whole sub. Public Sub CurrencyCheck() Dim ws As Worksheet Set ws = ActiveWorkbook.Worksheets("Datenbank") Dim lastRow As Long lastRow = ws.Cells(Rows.Count, 4).End(xlUp).Row Dim i As Long Dim j As Long Dim curSymbol As String Dim exchange As Currency Dim str As String Dim curArr() As String Dim arrCnt As Integer arrCnt = 1 Dim curInArr As Boolean curInArr = False Dim curIndex As Integer Dim validInput As Boolean ReDim curArr(1 To 2, 1 To arrCnt) For i = 1 To lastRow If ws.Cells(i, 4).Value <> "Price" And ws.Cells(i, 4).Value <> "" Then curSymbol = Get_Currency(ws.Cells(i, 4).text) 'Function that returns currency symbol (€) or abbreviation (EUR) If curSymbol <> "€" Then For j = LBound(curArr, 2) To UBound(curArr, 2) If curArr(1, j) = curSymbol Then curInArr = True curIndex = j End If Next j If Not curInArr Then If curSymbol = "EUR" Then ReDim Preserve curArr(1 To 2, 1 To arrCnt) curArr(1, arrCnt) = curSymbol curArr(2, arrCnt) = 1 curIndex = arrCnt arrCnt = arrCnt + 1 Else validInput = False Do Until validInput str = InputBox("Some text...") If str = vbNullString Then MsgBox ("Input canceled.") Exit Sub Else If IsNumeric(str) Then exchange = CCur(str) validInput = True Else MsgBox ("Input invalid.") End If End If Loop ReDim Preserve curArr(1 To 2, 1 To arrCnt) curArr(1, arrCnt) = curSymbol curArr(2, arrCnt) = exchange curIndex = arrCnt arrCnt = arrCnt + 1 End If End If ws.Cells(i, 4).Value = StringToCurrency(ws.Cells(i, 4).text) ws.Cells(i, 4).Value = ws.Cells(i, 4).Value * curArr(2, curIndex) ws.Cells(i, 4).NumberFormat = "#,##0.00 €" End If End If Next i End Sub EDIT2: When I run the input loop as a subroutine by itself it works. The macro is run in another workbook and doing that it fails... EDIT3: My bad. The problem is not related to the code but to the positioning of the subroutine. It was called of and over again because it was called in a loop. I have to apologize. Thanks to everyone.
This will loop until a numeric is entered: Sub dural() Dim validInput As Boolean Dim strg As String, x As Variant validInput = False Do strg = Application.InputBox(Prompt:="enter value", Type:=2) If strg = "False" Then ElseIf IsNumeric(strg) Then x = CCur(strg) validInput = True End If Loop Until validInput End Sub EDIT#1: This version will quit the loop if the user touches the CANCEL button or the red x button: Sub dural() Dim validInput As Boolean Dim strg As String, x As Variant validInput = False Do strg = Application.InputBox(Prompt:="enter value", Type:=2) If strg = "False" Or strg = "" Then validInput = True ElseIf IsNumeric(strg) Then x = CCur(strg) validInput = True End If Loop Until validInput End Sub
I don't think is a null string. Try this If str = vbNullString or str = "" Then
how to check OS system date format using excel vba
I am using excel 2007, ms visual basic 6.0. I required to check the window os date format (e.g, whether is it using d/m/yyyy or m/d/yyyy), in order to using the following code. Dim lastdateofmonth As Date Dim lastwhichday As String slastdayofmonth = "31" 'if the OS system is using m/d/yyyy then use this lastdateofmonth = (sTxtMMM + "/" + slastdayofmonth + "/" + TxtYYYY) lastwhichday = Weekday(lastdateofmonth) 'if th OS system is using d/m/yyyy then use this lastdateofmonth = (slastdayofmonth+ "/" + sTxtMMM + "/" + TxtYYYY) anyone can help? Thanks in advance
hmm... i found a better way '========== Check OS Date format======== Dim OSDateFormatType As Integer ' 0 = month-day-year; 1 = day-month-year; 2 = year-month-day If Application.International(xlDateOrder) = 0 Then OSDateFormatType = 0 ElseIf Application.International(xlDateOrder) = 1 Then OSDateFormatType = 1 ElseIf Application.International(xlDateOrder) = 2 Then OSDateFormatType = 2 End If But this only work for excel.
Check below code.... Sub getSystemDateFormat() Application.AskToUpdateLinks = False Application.DisplayAlerts = False If isSheetExists(ThisWorkbook, "Temp") = False Then ThisWorkbook.Sheets.Add After:=ThisWorkbook.Sheets(ThisWorkbook.Sheets.Count) ThisWorkbook.ActiveSheet.Name = "Temp" End If ThisWorkbook.Sheets("Temp").Cells(1, 1) = "" 'On Error GoTo ErrHandle 'Get Date format lngDateFormat = Application.International(xlDateOrder) 'Get Date Separator strDateSeparator = Application.International(xlDateSeparator) 'Get leading 0 for day If Application.International(xlDayLeadingZero) Then strDayFormat = "dd" Else strDayFormat = "d" End If 'Get leading 0 for month If Application.International(xlMonthLeadingZero) Then strMonthFormat = "mm" Else strMonthFormat = "m" End If 'Get 4 digit/2 digit format for year If Application.International(xl4DigitYears) Then strYearFormat = "yyyy" Else strYearFormat = "yy" End If 'Consolidate the values If lngDateFormat = 0 Then ' Month-Day-Year lngPos1 = InStr(1, Now(), strDateSeparator) If lngPos1 = 4 Then strMonthFormat = "mmm" End If strDateFormat = strMonthFormat & strDateSeparator & strDayFormat & strDateSeparator & strYearFormat ElseIf lngDateFormat = 1 Then ' Day-Month-Year lngPos1 = InStr(1, Now(), strDateSeparator) lngPos2 = InStr(lngPos1 + 1, Now(), strDateSeparator) If lngPos2 - lngPos1 = 4 Then strMonthFormat = "mmm" End If strDateFormat = strDayFormat & strDateSeparator & strMonthFormat & strDateSeparator & strYearFormat Else ' Year-Month-Day lngPos1 = InStr(1, Now(), strDateSeparator) lngPos2 = InStr(lngPos1 + 1, Now(), strDateSeparator) If lngPos2 - lngPos1 = 4 Then strMonthFormat = "mmm" End If strDateFormat = strYearFormat & strDateSeparator & strMonthFormat & strDateSeparator & strDayFormat End If MsgBox strDateFormat EndLine: ThisWorkbook.Sheets("Temp").Activate ThisWorkbook.Sheets("Temp").Cells(1, 1) = strDateFormat Exit Sub ErrHandle: If Err.Description <> "" Then ThisWorkbook.Sheets("Temp").Cells(1, 1) = Err.Description End If ThisWorkbook.Sheets("Temp").Activate End Sub Function isSheetExists(wbk As Workbook, strSheetName As String) As Boolean isSheetExists = False For i = 1 To wbk.Sheets.Count If wbk.Sheets(i).Name = strSheetName Then isSheetExists = True Exit For End If Next i End Function
The best way: if Application.International(xlMDY) then ... True - month, day, year False - day, month, year https://msdn.microsoft.com/en-us/library/office/ff840213%28v=office.15%29.aspx