ScreenUpdating not working when opening a file - macos

So I'm creating a library of commonly used macros for excel for my Excel 2011 for Mac. I'm running a couple of tests to make sure it's working properly. The biggest problem I'm running into is that when I run the code (despite having ScreenUpdating set to False), it visibly opens the library file while it runs the macro.
To make sure this is efficient going forward, I want to prevent that from happening. Here is currently what my code looks like:
Sub findRow()
Application.ScreenUpdating = False
Application.DisplayAlerts = False
Application.EnableEvents = False
Dim bk As Workbook
Dim result As Long
Dim aWB As Workbook
Dim aWS As Worksheet
Set aWB = ActiveWorkbook
Set aWS = ActiveWorkbook.ActiveSheet
With Application
.ScreenUpdating = False
.DisplayAlerts = False
.EnableEvents = False
Set bk = .Workbooks.Open _
(ActiveWorkbook.Path & ":library.xlsm")
'Set bk = ActiveWorkbook.Path & ":library.xlsm"
End With
'Workbooks.Open (ActiveWorkbook.Path & ":library.xlsm")
'Workbooks.Open (bk)
result = Application.Run("'" & ActiveWorkbook.Name & "'!findFirstEmptyRow", aWS)
ActiveWorkbook.Close
Cells(result, 1) = result
Application.ScreenUpdating = True
Application.DisplayAlerts = True
Application.EnableEvents = True
End Sub
There is quite a few redundancies in there as well as commented out lines that show various things I've tried. Originally I simply ran code that set Application.X settings to False, opened the Workbook, ran the macro, and closed.
Hopefully someone can come up with a reason for ScreenUpdating not taking effect when I open a new Workbook.

Setting ScreenUpdating to false only prevents spreadsheet updates from showing. It wont on its own hide the opening of a workbook. Although there are ways to hide the opening of a workbook, or access workbook data without creating an instance of Excel, for the task you're describing of creating a VBA library, the way to go about that is to create an Excel add-in. An add-in not only allows you to use a macro from any instance of Excel, but you can also edit your code and add new macros to a common repository from any instance also.

Related

Encoded VBS not working when called from HTA

We have an HTA used for automatic log in to the servers using VBS. To maintain security, we wanted to encode the VBS, which had the credentials for logging in to the server. We came across a VBS script that encoded the VBS file when dragged on to it, the output is a VBE file.
Now, when this VBE is called from HTA, it shows and error, which seems like it is not able to read the VBE properly.
Below is how we are linking the VBE to out HTA :
<script language="VBScript" src="hola.vbe" > </script>
Also, below is the code for encoding :
Option Explicit
dim oEncoder, oFilesToEncode, file, sDest
dim sFileOut, oFile, oEncFile, oFSO, i
dim oStream, sSourceFile
set oFilesToEncode = WScript.Arguments
set oEncoder = CreateObject("Scripting.Encoder")
For i = 0 to oFilesToEncode.Count - 1
set oFSO = CreateObject("Scripting.FileSystemObject")
file = oFilesToEncode(i)
set oFile = oFSO.GetFile(file)
Set oStream = oFile.OpenAsTextStream(1)
sSourceFile=oStream.ReadAll
oStream.Close
sDest = oEncoder.EncodeScriptFile(".vbs",sSourceFile,0,"")
sFileOut = Left(file, Len(file) - 3) & "vbe"
Set oEncFile = oFSO.CreateTextFile(sFileOut)
oEncFile.Write sDest
oEncFile.Close
Next
According to my understanding the encoded VBS should work as normal one, not sure why we are fading issue in this case.
In order to use an encoded VBScript, you need to specify the language engine to use with language="VBScript.Encode" rather than just language="VBScript".
Also, be quite wary if you want to use it "To maintain security". The purpose of the script encoder is to deter casual inspection, but it doesn't "encrypt" the code in any conventional sense, and it's not that hard to get the plain script back.

VB script will not traverse every file in a given folder

I am new to VBscript and am looking to write a simple script that changes a couple cells in a few thousand csv files in a given folder location. I have a good start, and it all seems to be working, except for the fact that when I run the script (from a .bat file that just calls the script) it only changes and moves 3-8 files at a time. The number of files it changes is random, its not like it always changes 5 files or something. I am not sure what is wrong in the code as to why it will not edit and move every single file and only does a couple at a time, here is what I have so far, thanks in advance for any help:
Set objFSO = Wscript.CreateObject("Scripting.FileSystemObject")
Set colFiles = ObjFSO.GetFolder("C:\Users\xxx\BadCSVs").Files
Set xl = CreateObject("Excel.Application")
For Each objFile in colFiles
If LCase(objFSO.GetExtensionName(objFile)) = "csv" Then
Set wb = xl.Workbooks.Open(objFile)
Set sht = xl.ActiveSheet
If(sht.Cells(1,11) <> "") Then
sht.Cells(1,8) = sht.Cells(1,8) & sht.Cells(1,9)
sht.Cells(1,9) = sht.Cells(1,10)
sht.Cells(1,10) = sht.Cells(1,11)
sht.Cells(1,11) = Null
wb.Save
wb.Close True
Else
'if file is opened up and has only 10 columns of data, then it makes no changes, then closes it.
wb.Close
End If
End If
Next
xl.Quit
Your EVIL global
On Error Resume Next
hides errors. Disable/Remove it and test again.
Your
wb.Close SaveChanges=True
passes the boolean result of comparing SaveChanges (undefined/empty) vs. the boolean literal True. Perhaps you copied VBA code
wb.Close SaveChanges:=True
(mark the colon) that is not legal in VBScript?
And
Set xl = CreateObject("Excel.Application")
should be paired with an
xl.Quit
If you invoke Excel in the loop, terminate it there. I would try to start/quit Excel out of the loop, but you should test that approach carefully.

vbscript to save sync issues folder emails to a folder

Background:
I am a sysadmin for several Windows 7 machines. We have switched from an on-premises Exchange server to Office 365 Exchange Online. The computers are using Outlook 2013/2010 to connect to Exchange Online. All the clients are using full cache mode, so there is a complete OST cache file on each computer.
Because of this, there are now the following folders showing in the Folder view of Outlook: Sync Issues, then (subfolders) Conflicts, Local Failures and Server Failures.
I could not find a way to remotely administer or view these messages, so my only option appears to be manually opening each user's Outlook and viewing the folders. I have tried setting up rules to forward any messages that appear in these folders to me, but I could not get them to work on new emails that appear in these folders.
I would like to write a script that will save the email messages in these folders to a network folder where I can view them later. I would also like to have the script run on an input text file of all the computer names on the network, if possible.
I have no script writing background or knowledge. This is what I have pieced together from the web so far:
Dim OL, NmeSpace
Set OL = CreateObject("Outlook.Application")
Set NmeSpace = OL.GetNamespace("MAPI")
Set Inbx = NmeSpace.GetDefaultFolder(olFolderSyncIssues)
Set Fldr = Application.ActiveExplorer.CurrentFolder
DirName = "C:\Emails\"
For Each itm In Fldr.Items
' Save email as a file.
Next
Thanks in advance for any advice you can offer. I am studying scripting but I do not have the knowledge yet to write the script I want.
Here is how you would go about doing that with a vbscript. Right now it only does the oSyncFolder as I left out the other two folders so you could get some practice writing it yourself.
Dim oApp
Dim ns
Dim oSyncFolder
Dim oConflictFolder
Dim oSrvFailuresFolder
Dim dirName
dirName = "PathToFolder\"
Set oApp = CreateObject("Outlook.Application")
Set ns = oApp.GetNamespace("MAPI")
Set oSyncFolder = ns.GetDefaultFolder(20)'olFolderSyncIssues
Set oConflictFolder = ns.GetDefaultFolder(19)'olFolderConflicts
Set oSrvFailuresFolder = ns.GetDefaultFolder(22)'olFolderServerFailures
Dim iCounter
iCounter = oSyncFolder.Items.Count
For iCounter = oSyncFolder.Items.Count To 0 Step -1
Dim oItem
Set oItem = oSyncFolder.Items.Item(iCounter)
oItem.SaveAs dirName & "email" & CStr(iCounter) & ".msg"
'uncomment line below to remove the item after it has been relocated.
'oItem.Delete
Next
Set oSyncFolder = Nothing
Set oConflictFolder = Nothing
Set oSrvFailuresFolder = Nothing
Set oApp = Nothing
msgbox "Finished"

How to close an application when vbscript crashes

I'm using VBscript to open Microsoft Excel and convert xls documents to csv.
Here is a quick example that takes an argument and converts the first page
Dim oExcel
Dim oBook
Set oExcel = CreateObject("Excel.Application")
Set oBook = oExcel.Workbooks.Open(Wscript.Arguments.Item(0))
oBook.SaveAs "out.csv", 6
oBook.Close False
oExcel.Quit
If everything works, that's great. But when the script crashes before it can close excel, the process continues to stay around and lock the file until I manually kill the process.
How can I make sure that I perform any clean up routines even when the script fails?
As the question is/was? about closing Excel reliably when the VBScript used to automate it crashes:
If you write
Set oExcel = CreateObject("Excel.Application")
you create a 'simple' variable. VBScript may decrement a ref counter when the variable goes out of scope, but it certainly won't .Quit Excel for you.
If you want a feature like atexit calls or exception handling in VBScript, you'll have to write a class that 'does what I mean' in its Class_Terminate Sub. A simple example:
Option Explicit
Class cExcelWrapper
Private m_oExcel
Public Sub Class_Initialize()
Set m_oExcel = CreateObject("Excel.Application")
End Sub
Public Sub Class_Terminate()
m_oExcel.Quit
End Sub
Public Default Property Get Obj()
Set Obj = m_oExcel
End Property
End Class
Dim oExcel : Set oExcel = New cExcelWrapper
Dim oWBook : Set oWBook = oExcel.Obj.WorkBooks.Add()
oExcel.Obj.Visible = True
oExcel.Obj.DisplayAlerts = False
oWBook.Sheets(1).Cells(1,1) = "Div by Zero"
WScript.Echo "Check TaskManager & Enter!"
WScript.StdIn.ReadLine
WScript.Echo 1 / 0
(meant to be started with "cscript 20381749.vbs")
If you run this script with an open Taskmanager, you'll see Excel popup in the processes list (and on the screen, because of .Visible). If you then hit Enter, the script will abort with an "Division by Zero" error and the Excel process will vanish from the Processes list.
If you remove the .DisplayAlerts setting, Excel will ask you whether to save your work or not - proving thereby that the .Quit from the Class_Terminate() Sub really kicks Excel into byebye mode.
The class needs further work (basic settings, common actions (save?) before .Quit, perhaps a guard against misuse (Set oExcel = Nothing or other cargo cult crap), th .Obj addition isn't nice, and it won't help you if you kill your .vbs in a debugger, but for standard scenarios you won't see Excel zombies anymore.
Add "On Error Goto ErrorHandler" at the top of your script, and at the bottom of it, add "ErrorHandler:". Underneath the ErrorHandler label add code to manage the situation depending on the Err.Number
See Err object on MSDN.
You can also use "On Error Resume Next". Here is an example.
EDIT: My bad. "Goto" does not exist in VBS. The answer below is probably a much tidier approach.

Save images in Outlook 2007

Programmatically, of course.
Having already asked this question on superuser, I'm looking at writing a simple macro to pull down the displayed image in an HTML message (email or feed) in outlook 2007, and allow me to save it to disk.
Unfortunately, I havent been able to find where in the OL object model I can reference either linked images, or the html content itself. Finding attached files is easy, its the linked/displayed images that is my issue.
Any help? Of course, if you have a better non-programmatic answer, I'll be glad to see that - over on superuser, of course...
This is based on the MSDN docs. I don't have Outlook to test it.
Assuming you have an email message open, you can call GetInspector method on the MailItem instance that you have & use its HTMLEditor property to get handle to the DOM.
From here on, you can call regular methods such as document.Images to get handle to all the image elements. I don't know, how one can save it locally to a disk but I am sure, there must be some method to do it.
I had a second look at shahkalpeshs answer and came up with the following solution:
(Written in Outlook 2003)
Option Explicit
Private Sub getImages()
Dim xmlhttp_ As xmlhttp
Dim htmldoc As Object
Dim currentImage As Object
Dim currentResponse() As Byte
Dim startTime As Date
Dim maxTime As Long
Dim pathFolder As String
Dim pathFull As String
Dim nrFile As Integer
pathFolder = "C:\YourFolder\Images\" '"(small fix for stackoverflow syntaxhighlighter)
maxTime = 30 ' max time to load 1 File in seconds '
If Me.ActiveWindow.CurrentItem.GetInspector.EditorType = olEditorHTML Then
Set htmldoc = Me.ActiveWindow.CurrentItem.GetInspector.HTMLEditor
Set xmlhttp_ = New xmlhttp
For Each currentImage In htmldoc.images
xmlhttp_.Open "GET", currentImage.src
If Left(currentImage.src, 8) <> "BLOCKED:" Then
xmlhttp_.Send
startTime = Now
pathFull = pathFolder & currentImage.nameProp
pathFull = Replace(pathFull, "?", vbNullString)
pathFull = Replace(pathFull, "&", vbNullString)
Do While xmlhttp_.readyState <> 4
If DateTime.DateDiff("s", startTime, Now) > maxTime Then Exit Do
DoEvents
Loop
If xmlhttp_.readyState = 4 Then
If Dir(pathFull) <> "" Then Kill pathFull
nrFile = freeFile
Open pathFull For Binary As #nrFile
currentResponse = xmlhttp_.responseBody
Put #nrFile, , currentResponse
Close #nrFile
End If
End If
Next currentImage
End If
Set xmlhttp_ = Nothing
Set currentImage = Nothing
Set htmldoc = Nothing
End Sub
This code will download all the images that are displayed in your ActiveWindow and save them in a folder.
You will need to add a Reference to Microsoft XML (any version >= 2.6 should work) through Tools->References in the VBA Editor
If you want to, you can also set a Reference to the Microsoft HTML Object Library and change:
Dim htmldoc As Object
Dim currentImage As Object
to:
Dim htmldoc As HTMLDocument
Dim currentImage As HTMLImg
Regarding your comment:
#marg, Thanks for the detailed response. I still cant believe the solution has to be so convoluted - the image is already displaying, why should I have to download it again? And what if I want to save only a single image? (In Outlook 2003, you were able to right click on the image and select save as... now no more.) Since this is the closes to an actual workable solution, and since there doesnt seem to be any better solution in current Outlook - i'm giving you the bounty...
I don't have 2007 to look for a non-programming solution.
I do not believe that the MailItem Object (CurrentItemin my solution is a MailItem) differs much between the versions (but I base that assumption on 0 % research :D) and I was not able to locate the direct local path where the displayed images are stored even though I am pretty sure they should be in your browsers cache-folder. Crawling your folder for a file with the name currentImage.nameProp and copying it to your destination folder would be an alternative solution. Simply redownloading the image should not be that bad :D

Resources