I have a problem with the following Code. What happens is that my PPT application crashes while running the code. It does not always happen and it happens in different parts of the code.
I tried the application.wait-method, but it did not work.
help is appreciated since I am already working on this for days -.-. Thanks in advance.
Option Explicit
Public myfilename As String
Sub filepicker()
Dim i As Variant
MsgBox ("In the following dialog please choose the current file")
Dim myfilenamepicker As FileDialog
Set myfilenamepicker = Application.FileDialog(msoFileDialogFilePicker)
myfilenamepicker.InitialFileName = "C:\Users\Michael\Desktop\Test PPT"
myfilenamepicker.Show
If myfilenamepicker.SelectedItems.Count <> 0 Then
myfilename = myfilenamepicker.SelectedItems(1)
End If
End Sub
Sub Saveas_PPT_and_PDF()
Dim PP As PowerPoint.Presentation
Dim sh As Variant
Dim company, strPOTX, strPfad, pptVorlage, newpath, newpathpdf As String
Dim Cell As Range
Dim pptApp As Object
Call filepicker
Application.ScreenUpdating = False
' set the dropdown from which the company Is Selected
Set DropDown.ws_company = Tabelle2
' the company is the value selected in the dropdown, stored in "C2"
company = DropDown.ws_company.Range("C2").Value
On Error Resume Next
Set pptApp = GetObject(, "PowerPoint.Application")
On Error Resume Next
If pptApp Is Nothing Then
Set pptApp = CreateObject("PowerPoint.Application")
End If
On Error GoTo 0
'loop through the companies in the dropdown menu
For Each Cell In DropDown.ws_company.Range(DropDown.ws_company.Cells(5, 3), _
DropDown.ws_company.Cells(Rows.Count, 3).End(xlUp)).SpecialCells(xlCellTypeVisible)
DropDown.ws_company.Range("C2") = Cell
pptVorlage = myfilename
Debug.Print (myfilename)
Set PP = pptApp.Presentations.Open(pptVorlage)
newpath = Replace(myfilename, "AXO", "" & Cell & " AXO")
PP.UpdateLinks
PP.SaveAs newpath
newpathpdf = Replace(newpath, "pptx", "pdf")
Debug.Print (newpathpdf)
PP.ExportAsFixedFormat "" & newpathpdf & "", ppFixedFormatTypePDF, ppFixedFormatIntentPrint
pptApp.Presentations(newpath).Close
Set PP = Nothing
Next
' this part below closes PPT application if there are no other presentation
' object open. If there is at least 1, it leaves it open
If IsAppRunning("PowerPoint.Application") Then
If pptApp.Windows.Count = 0 Then
pptApp.Quit
End If
End If
Set pptApp = Nothing
Set PP = Nothing
End Sub
Function IsAppRunning(ByVal sAppName) As Boolean
Dim oApp As Object
On Error Resume Next
Set oApp = GetObject(, sAppName)
If Not oApp Is Nothing Then
Set oApp = Nothing
IsAppRunning = True
End If
End Function
I don't see anything obviously wrong but I can give you a strategy for debugging.
You will want to test all major manipulations seperately. You will want to run each test in the debugger and have screenupdating on so you can see what happens:
test the filepicker
test GetObject/CreateObject - do you really need it? You already have PowrPoint open it seems;
test your loop with a single hardcoded value. What happens with the focus when opening a presentation?
try without UpdateLinks; try without SaveAs and try without Export (i.e. just open a presentation and close it again).
check if the presentation really closes, otherwise you might end up with lots of open presentations.
test closing the application
test reading from a dropdown box
test the IsAppRunning function. Note that it sets On Error Resume Next but does not reset it. Note it does not set IsAppRunning = False anywhere.
try relevant parts of the above in a loop with and without debugging to see what happens and see if it crashes - there could be a timing problem in the Office application, e.g. trying to manipulate a presentation while it is not yet fully loaded.
Minimising your code can help isolate the area that causes the problem. I hope this helps.
Related
I have an access database which prints a label as a word document. The word document is filled using the information from my access database and then closed. This works on my personal laptop and prints every time. When I transfer this to my work laptop it works the first time and then fails as the document has remained open. The document does not show up in the processes in task manager, my laptop is using office 365 and my work laptop is at office 2016 is this a version issue? Code below. If this is completely wrong could you please suggest the fix
Dim appWord As Word.Application
Dim doc As Word.Document
Dim thepath As String
thepath = CurrentProject.Path
'Avoid error 429, when Word isn't open.
On Error Resume Next
Err.Clear
'Set appWord object variable to running instance of Word.
Set appWord = GetObject(, "Word.Application")
If Err.Number <> 0 Then
'If Word isn't open, create a new instance of Word.
Set appWord = New Word.Application
End If
Set doc = appWord.Documents.Open(thepath & "\label.docx", , False)
'ActiveDocument.Tables(1).Cell(1, 1).va Me.PartNumber
'
'ActiveDocument.FormFields(fldPartNumber). = Me!PartNumber
If Selection.FormFields.Count >= 1 Then
MsgBox Selection.FormFields(1).Name
End If
ActiveDocument.FormFields("Text1").Result = Me.PartNumber
ActiveDocument.FormFields("Text2").Result = Me.SerialNumber
'MsgBox (ActiveDocument.FormFields("Text1").Result)
ActiveDocument.FormFields("Text10").Result = Me.BatchNumber
ActiveDocument.FormFields("Text7").Result = Me.Qty
ActiveDocument.FormFields("Text6").Result = Me.Lifex
ActiveDocument.FormFields("Text3").Result = Me.Station
ActiveDocument.FormFields("Text4").Result = Me.Store
ActiveDocument.FormFields("Text5").Result = Me.Bin
ActiveDocument.FormFields("Text11").Result = Me.Description
'.FormFields("fldCountry").Result = Me.Country
' FormFields("fldPhone").Result = Me.Phone
'.FormFields("fldFax").Result = Me.Fax
activedocuments.FormFields.Visible = True
'ActiveDocument.FormFields.Activate
appWord.DisplayAlerts = False
doc.PrintOut Background = True
appWord.DisplayAlerts = True
'CreateObject("Shell.Application").Namespace(0).ParseName("C:\Boeing Ireland Serviceable Label editable form.docx").InvokeVerb ("Print")
Set doc = Nothing
doc.Close
appWord.Quit (True)
Set appWord = Nothing
Exit Sub
ErrHandler:
MsgBox Err.Number & ": " & Err.Description
'
End Sub
I think that the problem is the order that you are doing things at the end of the code. You should be closing/quitting objects before setting them to nothing. In addition, I would recommend that you have a single exit section that cleans up objects, regardless of whether there is an error or not. Something like:
Sub sFoo
On Error GoTo E_Handle
' Word automation code here
sExit:
On Error Resume Next
doc.Close
Set doc=Nothing
appWord.Quit (True)
Set appWord=Nothing
Exit Sub
E_Handle:
MsgBox Err.Description
Resume sExit
End Sub
Regards,
Ok, the answer here was a known issue in Microsoft Office automation the document was left open due to failing to reference an object. Microsoft issue 189618 was the reference that i used to fix this.
{Cause
Visual Basic has established a reference to Word due to a line of code that calls a Word object, method, or property without qualifying it with a Word object variable. Visual Basic does not release this reference until you end the program. This errant reference interferes with automation code when the code is run more than once.
Resolution
Modify the code so that each call to a Word object, method, or property is qualified with the appropriate object variable.}
My original error catch was to use on error resume next which allowed the real issue Runtime error 426 to be bypassed. This was due to the line of code setting the doc reference as
`enter code here`Set doc = Documents.Open(thepath & "\label.docx",,False,,,,True)'
as it doesn't reference appword it leaves an instance open. Hence my second time round open document. The fix was simple.
Set doc= appword.Documents.Open(thepath & "\label".docx",,False,,,,True) The code now works, below is a fully corrected and cleaned up version of the script which includes Applecores suggestion that was so kindly provided.
Private Sub Command67_Click()
On Error GoTo E_Handle
Dim appwd As Word.Application
Dim doc As Word.Document
Dim thepath As String
thepath = CurrentProject.Path
Set appwd = CreateObject("Word.Application")
appwd.Visible = True
Set doc = appwd.Documents.Open(thepath & "\label.docx", , False, , , , True)
doc.FormFields("Text1").Result = Me.PartNumber
doc.FormFields("Text2").Result = Me.SerialNumber & nullstring
doc.FormFields("Text10").Result = Me.BatchNumber & nullstring
doc.FormFields("Text7").Result = Me.Qty
doc.FormFields("Text6").Result = Me.Lifex
doc.FormFields("Text3").Result = Me.Station
doc.FormFields("Text4").Result = Me.Store
doc.FormFields("Text5").Result = Me.Bin & nullstring
doc.FormFields("Text11").Result = Me.Description
appwd.DisplayAlerts = False
doc.PrintOut Background = True
appwd.DisplayAlerts = True
doc.Close SaveChanges:=wdDoNotSaveChanges
Set doc = Nothing
appwd.Quit
Set appwd = Nothing
Exit Sub
sExit:
On Error Resume Next
doc.Close
Set doc = Nothing
appwd.Quit
Set appwd = Nothing
Exit Sub
E_Handle:
MsgBox Err.Description
Resume sExit
End Sub
I have an application that first creates an invisible application:
Dim ExcelApp As Object
Set ExcelApp = CreateObject("Excel.Application")
ExcelApp.Visible = False
ExcelApp.ScreenUpdating = False
ExcelApp.DisplayAlerts = False
ExcelApp.EnableEvents = False
And then proceeds to use it to open files invisibly:
Do While fileTitle <> ""
Dim dataWorkbook As Workbook
Set dataWorkbook = ExcelApp.Application.Workbooks.Open(folderPath & fileTitle)
At the end of the operations with the file macros closes the file:
dataWorkbook.Close
fileTitle = Dir()
Loop
At the end of the sub macros closes the application:
ExcelApp.Quit
Set ExcelApp = Nothing
End Sub
However, if an error occurs before the file is closed, the invisible file and the application would never be closed and would continue to linger in operation systems not only eating away the memory and resources, but also preventing from doing any operations with the opened filed - renaming, opening or editting it.
I wonder if there is a way to close both the file and the application if an error occurs - in the current macros or to create a separate macros that detects invisible applications no variable points to and closes it.
At the top of your procedure use an error handler like
Set ExcelApp = CreateObject("Excel.Application")
On Error Goto CLOSE_FILE_ON_ERROR
'With that line you tell VBA to jump to the closing part if an error happens
and use this goto marker before you close the file.
CLOSE_FILE_ON_ERROR:
ExcelApp.Quit
End Sub
Note: You don't need to Set ExcelApp = Nothing because Excel does this automatically on End Sub.
Edit due to comments
If you need to show error messages or something then your code has to be extended like this:
ExcelApp.Quit 'This is needed to regularly quit if there is no error
Exit Sub 'Don't run into error handling if there was no exeption
CLOSE_FILE_ON_ERROR:
Application.StatusBar = "Error occured"
ExcelApp.Quit 'This is needed to quit after an exeption if there is an error
End Sub
You can try the below code where I kill the application like Excel, Chrome and Internet Explorer. You can use the below code with the On Error Goto error handler.
Public Function fnkilltask()
Dim objWMIService
Dim colProcessList
Dim objProcess
Dim strComputer
strComputer = "."
Set objWMIService = GetObject("winmgmts://./root/cimv2") ' Task mgr
Set colProcessList = objWMIService.ExecQuery ("Select * from Win32_Process Where Name in ('EXCEL.EXE','Chrome.exe','iexplore.exe') ")
For Each objProcess in colProcessList
objProcess.Terminate()
Next
End Function
I am able to export Charts as JPG files from Powerpoint, but haven't been able to do this with a table, which as far as I can tell is still a "Shape" which should be able to export.
This is a cleansed version of the code I use to export the Chart as JPG.
Const imgFilePath as String = "ChartImage.JPG"
Sub ExportChartJPG()
Dim cht as Variant 'this will hold the Chart/Shape object
Set cht = ActivePresentation.Slides(1).Shapes("Chart1").Chart
On Error Resume Next
Kill imgPath
On Error GoTo 0
cht.Export imgPath, "JPG"
End Sub
I figured this would be simple to modify, like:
Sub ExportChartJPG()
Dim cht as Variant 'this will hold the Chart/Shape object
Set cht = ActivePresentation.Slides(1).Shapes("Table1").Table
On Error Resume Next
Kill imgPath
On Error GoTo 0
cht.Export imgPath, "JPG"
End Sub
But this is throwing an error 13 Mismatch.
I have also tried dimensioning cht as a Shape instead of Variant, and setting cht = ActivePresentation.Slides(1).Shapes("Table1"), also unsuccessfully.
Although KazJaw's solution works, it was a bit cumbersome (copying takes additional time to process, I was getting errors I think as a result of not "waiting" long enough for the copy to complete, clipboard issues? etc.)
http://www.tech-archive.net/pdf/Archive/Office/microsoft.public.office.developer.vba/2006-10/msg00046.pdf
I open the object browser, right-click, and show hidden methods, which now allows me to use the Export method on a Shape.
Sub ExportShapeJPG()
Dim cht as Variant 'this will hold the Chart/Shape object
Set cht = ActivePresentation.Slides(1).Shapes("Table1") '<-- removed .Table and only pass the Shape itself
'Likewise, for charts, omit the .Chart:
' Set cht = ActivePresentation.Slides(1).Shapes("Chart1")
On Error Resume Next
Kill imgPath
On Error GoTo 0
cht.Export imgPath, ppShapeFormatJPG '<-- The export syntax is slightly different using ppShapeFormatJPG instead of "JPG"
End Sub
I have one quite weird idea. Look at the code where first part save a chart and second save table.
Sub ExportinChartAndTable()
Dim imgFilePath As String
imgFilePath = ActivePresentation.Path & "\chart"
Dim shp As Shape
Set shp = ActivePresentation.Slides(1).Shapes(1)
Dim shpChart As Chart
Set shpChart = shp.Chart
'exporting chart
On Error Resume Next
Kill imgFilePath
On Error GoTo 0
shpChart.Export imgFilePath & "chart.jpg", "JPG"
Stop
Dim chartPart As ChartData
Set chartPart = shpChart.ChartData
imgFilePath = ActivePresentation.Path & "\dataTable.jpg"
chartPart.Workbook.worksheets("arkusz1").Range("a1:c20").Copy
shpChart.Paste
shpChart.Shapes(1).Width = shp.Width
shpChart.Shapes(1).Height = shp.Height
On Error Resume Next
Kill imgFilePath
On Error GoTo 0
shpChart.Export imgFilePath, "JPG"
End Sub
You have to come up with idea how to check the range of the table. I hoped that CurrentRegion would work but it's not. You could use the possibility to count the amount of rows and columns in the table (it is possible). Or maybe you have fixed range so it would be easy. One more thing, you have to adjust dimension when table is resized.
EDIT due to David comment. I keep the above solution in place as could be useful for others (please refer to comments below)
Sub SolutionSecond()
Dim whereTo As String
whereTo = ActivePresentation.Path & "\table.jpg"
Dim shp As Shape
Set shp = ActivePresentation.Slides(1).Shapes(1)
Dim chrt As Shape
Set chrt = ActivePresentation.Slides(1).Shapes.AddChart
shp.Copy
'required due to excel opening proces
chrt.Select
chrt.Chart.Paste
'set dimensions here
chrt.Chart.Export whereTo, "JPG"
chrt.Delete
End Sub
This one base on the same logic. Copy table into chart which (the only kind of Shape) could be exported.
I posted earlier about getting my VBScript to wait until a process had finished before continuing (further info: VBScript - How to make program wait until process has finished?.
I was given an adequate answer after some discussion. However, it seems that I am now going in a new direction with the code as the solution presented another problem that I am hoping you may be able to help me with.
Basically I have some code which I have provided below. It takes in 4 arguments, one of which is a PATH to a folder containing many files which I want to use along with the other three in my VBA macro.
If WScript.Arguments.Count = 4 Then
' process input argument
Set args = WScript.Arguments
arg1 = args.Item(0)
arg2 = args.Item(1)
arg3 = args.Item(2)
arg4 = args.Item(3)
' Create a WshShell instance
Dim WShell
Set WShell = CreateObject("WScript.Shell")
' Create an Excel instance
Dim x1
Set x1 = CreateObject("Excel.Application")
' Disable Excel UI elements
x1.DisplayAlerts = False
x1.AskToUpdateLinks = False
'x1.AlertBeforeOverwriting = False
x1.FeatureInstall = msoFeatureInstallNone
' Open the Workbooks specified on the command-line
Dim x1WB
Dim x2WB
Dim x3WB
Dim x4WB
Dim strWB1
Dim strWB2
Dim strWB3
Dim strWB4
Dim FSO
Dim FLD
Dim FIL
Dim strFolder
strWB1 = arg1
Set x1WB = x1.Workbooks.Open(strWB1)
' Show the workbook/Excel program interface. Comment out for silent running.
x1WB.Application.Visible = True
strWB2 = arg2
Set x2WB = x1.Workbooks.Open(strWB2)
' Show the workbook/Excel program interface. Comment out for silent running.
x2WB.Application.Visible = True
strWB3 = arg3
Set x3WB = x1.Workbooks.Open(strWB3)
' Show the workbook/Excel program interface. Comment out for silent running.
x3WB.Application.Visible = True
'To hold the string of the PATH to the multiple files
strFolder = arg4
Set FSO = CreateObject("Scripting.FileSystemObject")
'Get a reference to the folder I want to search
set FLD = FSO.GetFolder(strFolder)
Dim strMyMacro
strMyMacro = "my_excel_sheet_with_vba_module.xlsm!Sheet1.my_vba_macro"
'loop through the folder and get the file names
For Each Fil In FLD.Files
WshShell.run """C:\Program Files\Microsoft Office\Office14\EXCEL.exe"" " & Fil, 1, true
x1.Run strMyMacro
'~~> Problem - How do I get the macro to run before opening the above file but run after it has opened (due to setting the bWaitOnReturn to true)
'~~> Problem - How do I get the file on current iteration to close after the macro has completed?
'~~> Problem - If this is not the issue, can you identify it?
Next
x1WB.close
x2WB.close
x3WB.close
'x4WB.close
' Clean up and shut down
Set x1WB = Nothing
Set x2WB = Nothing
Set x3WB = Nothing
Set x4WB = Nothing
Set FSO = Nothing
Set FLD = Nothing
x1.Quit
Set x1 = Nothing
Set WshShell = Nothing
WScript.Quit 0
Else
WScript.Quit 1
End If
The script works like this:
4 arguments are passed to the script. The 3rd argument is a .xlsm file which contains my VBA macro. The last argument is a PATH to a folder containing multiple files.
It then opens up the first three Excel files.
Then I run a loop to iterate through the files Fil in the folder that was specified as the 4th argument. AFAIK this has to be done via a WScript.shell using the .run method so that the rest of the script will hang until the Excel file it is processing finishes before closing it and opening up the next file in the folder.
After opening up file Fil, I then run the macro (albeit at this moment in time unsuccessfully).
I was tempted to simply open up all of the Excel files using the WScript.shell object however AFAIK I would not be able to run the macro this way.
Hopefully I have been able to define my aims of this piece of VBScript though if I haven't let me know and I shall clarify. Can you help?
Thanks,
QF.
Something along these lines might work for you (in Excel). A few things I'm not clear on though:
Where is your existing VBA macro - I'm guessing it's in one of the 3 files you're opening?
What types of files are in the folder you're looping through? I guessed Excel.
How is the vbscript being run? It looks like you're shelling out from your HTA, but why not include it directly in the HTA? That would save you from having to shell out and pass arguments...
Option Explicit
Dim wb1 As Workbook, wb2 As Workbook
Sub ProcessFolder(path1, path2, sFolder)
Dim wb As Workbook
Dim s
Set wb1 = Workbooks.Open(path1)
Set wb2 = Workbooks.Open(path2)
If Right(sFolder, 1) <> "\" Then sFolder = sFolder & "\"
s = Dir(sFolder & "*.xls*", vbNormal)
Do While Len(s) > 0
Set wb = Workbooks.Open(sFolder & s)
ProcessFile wb
wb.Close False
s = Dir()
Loop
wb1.Close False
wb2.Close False
End Sub
Sub YourExistingMacro(wb As Workbook)
'do stuff with wb and presumably the other 3 open files...
End Sub
I am trying to use this code snippet to get the selected text in outlook 2003
Sub SelectedTextDispaly()
On Error Resume Next
Err.Clear
Dim oText As TextRange
''# Get an object reference to the selected text range.
Set oText = ActiveWindow.Selection.TextRange
''# Check to see whether error occurred when getting text object
''# reference.
If Err.Number <> 0 Then
MsgBox "Invalid Selection. Please highlight some text " _
& "or select a text frame and run the macro again.", _
vbExclamation
End
End If
''# Display the selected text in a message box.
If oText.Text = "" Then
MsgBox "No Text Selected.", vbInformation
Else
MsgBox oText.Text, vbInformation
End If
End Sub
When running this macro I get the error
---------------------------
Microsoft Visual Basic
---------------------------
Compile error:
User-defined type not defined
Do I need to add any references to fix this up?
#Kusleika, I tried the option you had suggested and still the same errors came up.
Thanks for the help
May be I had not phrased my question in the proper way
Some more googling revealed that its not possible to get the selected text of a mail in preview pane. http://www.eggheadcafe.com/forumarchives/outlookprogram_VisualBasica/Aug2005/post23481044.asp
So I had to adjust the requirement so that I can do an action from an mail item window.
The following code helped me (had to make some changes to suit my needs)
Sub Blue_Code_Highlight()
Dim msg As Outlook.MailItem
Dim insp As Outlook.Inspector
Set insp = Application.ActiveInspector
If insp.CurrentItem.Class = olMail Then
Set msg = insp.CurrentItem
If insp.EditorType = olEditorHTML Then
Set hed = msg.GetInspector.HTMLEditor
Set rng = hed.Selection.createRange
rng.pasteHTML "<font style='color: blue; font-family:Times New Roman; font-size: 10pt;'>" & rng.Text & "</font><br/>"
End If
End If
Set insp = Nothing
Set rng = Nothing
Set hed = Nothing
Set msg = Nothing
End Sub
Source:http://www.outlookcode.com/threads.aspx?forumid=4&messageid=26992
#Kusleika thanks for the help, can I close this thread. Pls let me know.
Just in case someone is using the word editor instead of html, you can also insert this part:
If insp.EditorType = olEditorWord Then
Set hed = msg.GetInspector.WordEditor
Set word = hed.Application
Set rng = word.Selection
rng.Font.Name = "Times New Roman"
rng.Font.Size = 10
rng.Font.Color = wdColorBlack
End If
to get similar when word is the editor. i tried to paste this into a comment on the accepted answer, but it destroyed the formatting and was pretty useless, so posting as an answer.
Dim oText As Range
TextRange is a property of the TextFrame object. It returns a Range object. There is no TextRange object.