Excel VBA to refresh from MySQL - vba

I have this code to refresh my connections from excel to MySQL, I made it in such a way when someone tries to refresh in a PC that is not in the network it would throw a msg saying sever connection lost..
It only does the refresh part but when I use the excel file in a PC not connected to the network it doesn't show my custom message.
Sub refreshall()
Dim answer As Integer
Dim wSheet As Worksheet
On Error GoTo Handler
answer = MsgBox("Refresh All Sheets At Once?", vbYesNo + vbQuestion, "Refresh All")
If answer = vbYes Then
Application.DisplayAlerts = False
Application.ScreenUpdating = False
For Each wSheet In Worksheets
wSheet.Unprotect Password:="Secret"
Next wSheet
ActiveWorkbook.refreshall
For Each wSheet In Worksheets
wSheet.Protect Password:="123", UserInterfaceOnly:=True, _
AllowFiltering:=True, _
AllowSorting:=True, _
AllowUsingPivotTables:=True
Next wSheet
Application.DisplayAlerts = True
Application.ScreenUpdating = True
Exit Sub
Else
Exit Sub
End If
Exit Sub
Handler:
For Each wSheet In Worksheets
wSheet.Protect Password:="123", UserInterfaceOnly:=True, _
AllowFiltering:=True, _
AllowSorting:=True, _
AllowUsingPivotTables:=True
Next wSheet
MsgBox "Server Connection Lost...", vbOKOnly + vbCritical, "Warning"
Exit Sub
End Sub

As I understand, exactly ActiveWorkbook.refreshall throws handler section when your PC is connected to the network.
I guess Excel itself detects that there is no network and don't execute some part of its own algorithms inside of RefreshAll sub so ActiveWorkbook.refreshall execution in this case causes no exeptions.

Related

Excel VBA with Application.ScreenUpdating does not work

I have a macro in excel VBA which runs other macros. I am trying to implement Application.Screenupdating so that the user does not get to see what the macros do. However it seems to work for every macro, other than AccImport which is the main macro that I do not want my user to be aware of.
This macro does a spreadsheet transfer from excel to access, and I do not want my users to be aware of my access database. Within this macro it does a spreadsheet transfer by opening the access database, then closing it. Below is the main macro that I trigger, screenupdating=false seems to work for all the macros other than AccImport.
Any ideas? Thank you.
Sub ENTER1Dim2()
'
' ENTER1 Macro
'
'
If Worksheets("DIM21").Range("AR32") = 0 Then
MsgBox "Please enter DATA completely first"
End
Else
Application.ScreenUpdating = False
Application.Run "'NEW.xlsm'!TransferE1Dim2"
Application.ScreenUpdating = False
Application.Run "'NEW.xlsm'!PWDOFF"
Application.ScreenUpdating = False
Application.Run "'NEW.xlsm'!ProtectE1Dim2"
Application.ScreenUpdating = False
Application.Run "'NEW.xlsm'!UnprotectE2Dim2"
Application.ScreenUpdating = False
Application.Run "'NEW.xlsm'!ClearE2Dim2"
Sheets("Data1").Select
Application.ScreenUpdating = False
Application.Run "'NEW.xlsm'!AccImport"
Sheets("DIM21").Select
Range("G41").Select
Application.Run "'NEW.xlsm'!PWDON"
Call AUTOSAVE
End If
Application.ScreenUpdating = True
End Sub
Macro below is AccImport.
Sub AccImport()
'Application.OnTime Now + TimeValue("00:01"), "AccImport"
Dim Acc As New Access.Application
Acc.OpenCurrentDatabase "C:\Users\yilmadu001\Desktop\Database.accdb"
Acc.DoCmd.TransferSpreadsheet _
TransferType:=acImport, _
SpreadSheetType:=acSpreadsheetTypeExcel12Xml, _
TableName:="Table1", _
Filename:=Application.ActiveWorkbook.FullName, _
HasFieldNames:=True, _
Range:="Data1$A1:BL40000"
Acc.CloseCurrentDatabase
Acc.Quit
Set Acc = Nothing
End Sub

Macro enabled workbook not running

I'm trying to ensure that for each row in my spreadsheet, if cell B or C is not populated (in the range), then a message box alerts the user - and doesn't allow it to be saved.
I have the workbook saved as a Macro enabled (XLSM) file - but the Workbook_BeforeSave doesn't appear to be triggering.
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
Dim rng1 As Range
Dim rng2 As Range
MsgBox "hi"
Set rng1 = ActiveSheet.Range(ActiveSheet.Cells(1, 1), ActiveSheet.Cells(3, 4)).Select
Stop
'turn off events to avoid code retriggering itself
Application.EnableEvents = False
For Each rng2 In rng1
If Cells(rng2.Row, "B") = vbNullString Then
MsgBox "Please Enter Something in Cell B - your entry will be deleted", vbOKOnly
rng2.Value = vbNullString
End If
If Cells(rng2.Row, "C") = vbNullString Then
MsgBox "Please Enter Something in Cell C - your entry will be deleted", vbOKOnly
rng2.Value = vbNullString
End If
Next
Application.EnableEvents = True
End Sub
Can anyone see where I may have gone wrong? Macros are enabled for the workbook.
Thanks for any advice,
Mark
Somehow in your code, you have disabled the events, thus the Save event is not caught. Try the following:
Press Ctrl + G, while you are selecting the Visual Basic Editor;
Write Application.EnableEvents = True on the Immediate window that shows up;
Press Enter;
Now the events would be activated.
As mentioned by Jeep, using error handling is a good idea in this case, thus the events are always enabled back if something "bad" happens during code execution:
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
On Error GoTo Workbook_BeforeSave_Error
'code here
On Error GoTo 0
Exit Sub
Workbook_BeforeSave_Error:
Application.EnableEvents = True
MsgBox "Error " & Err.Number & " (" & Err.Description & ") in Workbook_BeforeSave"
End Sub

Copy and Paste with criteria VBA or Filter

My name is Pedro and I am very beginner in VBA development. I have a question about copy and paste with criteria. I have code that reports to me an error 1004 workbooks open when I run a macro that copy and paste row in another workbooks. How can I fix this error with the following code?
Dim LastRow As Integer, i As Integer, erow As Integer
LastRow = ActiveSheet.Range("A" & Rows.Count).End(xlUp).Row
Application.ScreenUpdating = False
Application.Calculation = xlManual
For i = 2 To LastRow
'If Cells(i, 9) = "Aline" Then
'Range(Cells(i, 1), Cells(i, 16)).Select
'Selection.Copy
'Workbooks.Open Filename:="L:\Controle\Assessoria Tecnica\Pessoas\Aline.xlsx"
'Worksheets("Plan1").Select
'erow = ActiveSheet.Cells(Rows.Count, 1).End(xlUp).Offset(1, 0).Row
'ActiveSheet.Cells(erow, 1).Select
'ActiveSheet.Paste
'ActiveWorkbook.Save
'ActiveWorkbook.Close
'Application.CutCopyMode = False
End If
Next i
Application.ScreenUpdating = True '
Application.Calculation = xlCalculationAutomatic
MsgBox "Informações inseridas com sucesso", vbInformation
End sub
I also want to explain what my code do it. My code matches a specific condition in "I" column (like Aline, Carol, Karine, Lucas, Thiago) and after that it copies each row and pastes it in another workbook, according to the matched conditions in "I" column. So what do you think would be the problem in this situation? What can i do to fix the error? Or make a new code that copy a row with condition and paste it in another workbooks?
As for your posted code, you've commented your IF block but not the entire thing. The END IF should also be commented.
I've done similar things in the past, so let me offer some code snippets as advice. This should get you started. This is by no means the right or perfect way to do things, but it is simple to understand. After years and years of writing VB, I wouldn't write it this way. :)
Sub Open_SlaveWB()
vFile = Workbooks.Open Filename:="L:\Controle\Assessoria Tecnica\Pessoas\Aline.xlsx"
If TypeName(vFile) = "Boolean" Then Exit Sub
Set UpdateSheet = wbMaster.Sheets("Update") 'Name of the sheet in the master WB to copy into
Set wbSlave = Workbooks.Open(vFile)
Set SlaveSheet = wbSlave.Sheets("Plan1") 'Name of the sheet in the slave WB to copy from
Exit Sub
errMessage:
MsgBox Err.Number & vbCrLf & Err.Description, vbCritical, "Error!"
Resume Next
End Sub
If you're absolutely sure the path and file name will go unchanged use this, otherwise I would advise setting vfile to: Application.GetOpenFilename("Excel-files,*.xlsx", 1, "Select One File To Open", , False) which will open a file select dialog box.
I've found it more efficient to copy the sheet, to your master workbook, and get the data from there rather than subsequent slave workbooks.
Sub Copy_SlaveToMaster()
LastSlaveRow = SlaveSheet.UsedRange.Rows.Count
LastSlaveColumn = SlaveSheet.UsedRange.Columns.Count
SlaveSheet.Range(Cells(1, 1), Cells(LastSlaveRow, LastSlaveColumn)).Copy
UpdateSheet.Cells(1, 1).PasteSpecial
Exit Sub
errMessage:
MsgBox Err.Number & vbCrLf & Err.Description, vbCritical, "Error!"
Resume Next
End Sub
You obviously don't need the slave WB to stay open.
Sub Close_SlaveWB()
Application.DisplayAlerts = False
wbSlave.Close
Application.DisplayAlerts = True
Exit Sub
errMessage:
MsgBox Err.Number & vbCrLf & Err.Description, vbCritical, "Error!"
Resume Next
End Sub
From there you would just write some code to manipulate the new sheet, use the data from the new sheet as you wish.

VBA "Application-defined or Object-defined error" when protect a worksheet

I'm writing a VBA macro that protects another workbook when user clicks a button and open it via current workbook. I got "Application-defined or Object-defined error". I looked into this post and made sure that the workbook that needs to be opened is unprotected. But the error still occurs. Please help. Thanks!
Sub LockModelParInput()
Dim wbk As Workbook
Workbooks.Open (ModelParVarClusLocalPath & "\" & ProN & "_ModelParameter_UserInput.xlsx")
Set wbk = Workbooks(ProN & "_ModelParameter_UserInput.xlsx")
wbk.Activate
With ActiveWorkbook.Worksheets("Model_Rule")
.Protection.AllowEditRanges.Add Title:="VIF Cut Off Level 2", _
Range:=Range("C4") *'error occurs on this line*
.Protection.AllowEditRanges.Add Title:="p_value stay", Range:= _
Range("D4")
.Protection.AllowEditRanges.Add Title:="Trend Threshold", Range _
:=Range("E4")
.Protection.AllowEditRanges.Add Title:="r_var_ks_penalize", Range _
:=Range("B10")
.Protection.AllowEditRanges.Add Title:="fast backward", Range:= _
Range("C16")
.Protection.AllowEditRanges.Add Title:="locked forward", Range:= _
Range("C17")
.Protection.AllowEditRanges.Add Title:="enhanced stepwise", Range _
:=Range("C18")
.Protection.AllowEditRanges.Add Title:="traditional backward", _
Range:=Range("C19")
.Protection.AllowEditRanges.Add Title:="sas stepwise", Range:= _
Range("C21")
.Protect DrawingObjects:=True, Contents:=True, Scenarios:=True
End With
End Sub
You need to check to see if the edit range's title has already been used - they can't be duplicated. Just knock up a quick function like this to iterate them:
Private Function EditRangeExists(Sh As Worksheet, Title As String) As Boolean
With Sh.Protection
Dim found As AllowEditRange
For Each found In .AllowEditRanges
If found.Title = Title Then
EditRangeExists = True
Exit Function
End If
Next
End With
End Function
...then check to make sure you're not attempting to add duplicates. I'd use a small wrapper for the test to make your code cleaner:
Private Sub TryAddProtectionRange(Title As String, Target As Range)
With Target
If EditRangeExists(Target.Parent, Title) Then
Exit Sub
End If
.Parent.Protection.AllowEditRanges.Add Title, Target
End With
End Sub
Then you can use it like this:
Sub LockModelParInput()
Dim wbk As Workbook
Set wbk = Workbooks.Open(ModelParVarClusLocalPath & "\" & ProN & _
"_ModelParameter_UserInput.xlsx")
Dim Sh As Worksheet
Set Sh = wbk.Worksheets("Model_Rule")
With Sh
TryAddProtectionRange "VIF Cut Off Level 2", .Range("C4")
TryAddProtectionRange "p_value stay", .Range("D4")
'Etc.
.Protect DrawingObjects:=True, Contents:=True, Scenarios:=True
End With
End Sub
I'd add some sort of error handling and/or have TryAddProtectionRange return a Boolean for success also.

Isolate Excel VBA script to run aginst specific worksheets?

I have an Excel spreadsheet that contains 7 worksheets.
I need the script below to be applied to only some of the worksheets (Sheet6 & Sheet7) whenever the document is saved.
I've spent several hours trying different modifications, must of which simply did not work. The VBA debugger does not throw any errors, and when I test the script it never appears to run.
How can the script below be modified to run against specific worksheets, whenever I save the document from any of the worksheet tabs?
Thank you
VBA - Lock Cells & Protect Sheet On Save
The script below will lock cells that contain values, and then password protect the sheet before saving.
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
On Error Resume Next
Dim Cell As Range
With ActiveSheet
.Unprotect Password:=""
.Cells.Locked = False
For Each Cell In Application.ActiveSheet.UsedRange
If Cell.Value = "" Then
Cell.Locked = False
Else
Cell.Locked = True
End If
Next Cell
.Protect Password:=""
'Protect with blank password, you can change it
End With
Exit Sub
End Sub
Script Source
Change the ActiveSheet and use a For Each loop like so:
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
On Error Resume Next
Dim Cell As Range
For Each sh In Array("Sheet1", "AnotherSheet", "OtherSheet")
With Sheets(sh)
.Unprotect Password:=""
.Cells.Locked = False
For Each Cell In Application.ActiveSheet.UsedRange
If Cell.Value = "" Then
Cell.Locked = False
Else
Cell.Locked = True
End If
Next
.Protect Password:=""
End With
Next
End Sub
This should help you (you'll have messages to let you know when you are in the event and when it's started and over) :
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
Dim Cell As Range
MsgBox "Event Workbook_BeforeSave Launched", vbInformation + vbOKOnly, "Started"
On Error GoTo ErrHandler
ReTry:
With Sheet6
.Unprotect Password:=""
.Cells.Locked = False
For Each Cell In .UsedRange
If Cell.Value = "" Then
Cell.Locked = False
Else
Cell.Locked = True
End If
Next Cell
.Protect Password:=""
'Protect with blank password, you can change it
End With
With Sheet7
.Unprotect Password:=""
.Cells.Locked = False
For Each Cell In .UsedRange
If Cell.Value = "" Then
Cell.Locked = False
Else
Cell.Locked = True
End If
Next Cell
.Protect Password:=""
'Protect with blank password, you can change it
End With
MsgBox "Event Workbook_BeforeSave Over", vbInformation + vbOKOnly, "Finished"
Exit Sub
ErrHandler:
MsgBox "Error " & Err.Number & " :" & vbCrLf & _
Err.Description
Resume ReTry
End Sub
The code can be significantly shorted (run time wise) by
Using SpecialCells rather than looping through each cell
avoiding setting blank cells as being locked twice (minor compared to first point).
updated
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
For Each sh In Array("Sheet1", "AnotherSheet", "OtherSheet")
With Sheets(sh)
.Unprotect
.Cells.Locked = True
On Error Resume Next
.Cells.SpecialCells(xlBlanks).Locked = False
On Error GoTo 0
.Protect
End With
Next
End Sub