Confirm prompt using Powershell - excel

I'm using powershell to automate a daily task. It is essentially a macro to refresh data linked to an external source and then sends an email out. The issue is that Excel automatically prompts for username/password whenever it tries to refresh the data. I did some digging and it can not be bypassed by setting DisplayAlert = False and cannot be changed from Excel's settings. My credentials are saved so what I really need to do is to have a script to press on "Enter".
I have the following set up currently: using Windows Scheduler, I first launch a Powershell script that'll open up Excel and run the macro to refresh the data. The macro will be stuck when Excel prompts for credentials. I have a second task which is scheduled to run 2 minutes after the first one and its purpose is to press on "Enter" to get rid of the prompt.
I have tried a couple of scripts for the second task but I just can't seem to get it right.
What I have tried is as follows:
[void] [System.Reflection.Assembly]::LoadWithPartialName("'Microsoft.VisualBasic")
[void] [System.Reflection.Assembly]::LoadWithPartialName("'System.Windows.Forms")
$wshell = New-Object -ComObject wscript.shell;
$wshell.AppActivate("Windows Security")
[System.Windows.Forms.SendKeys]::SendWait("{ENTER}")
and
$excel = [Runtime.Interopservices.Marshal]::GetActiveObject('Excel.Application')
[void] [System.Reflection.Assembly]::LoadWithPartialName("'Microsoft.VisualBasic")
[void] [System.Reflection.Assembly]::LoadWithPartialName("'System.Windows.Forms")
[System.Windows.Forms.SendKeys]::SendWait("{ENTER}")
Any idea on how I can bypass/accept the prompt?
Thanks in advance.

We use a solution slightly different from what you already tried. Maybe it is in the details...
[void] [System.Reflection.Assembly]::LoadWithPartialName
("'Microsoft.VisualBasic")
[Microsoft.VisualBasic.Interaction]::AppActivate("Windows Security")
[void] [System.Reflection.Assembly]::LoadWithPartialName("'System.Windows.Forms")
[System.Windows.Forms.SendKeys]::SendWait("{ENTER}")

Please share the data link for more details, however, I would simply recreate the data link programmatically if indeed there is a reason why the pass & login can be saved e.g. a macro accepting pass and login
If it's a SQL connection then it would look something like this:
Sub Recreate(serverInstance as String, database as String, userId as String, password as String)
sConn = "OLEDB;Provider=SQLOLEDB;Data Source=" & _
serverInstance & ";Initial Catalog=" & database & _
";User ID=" & userId & ";Password=" & password & ";"
Set qt = wks.QueryTables.Add(Connection:=sConn, _
Destination:=Target)
With qt
.CommandType = xlCmdSql
.CommandText = sql
.Name = sName
.RefreshStyle = xlOverwriteCells
.Refresh BackgroundQuery:=False 'Execute SQL
End With
End Sub

Related

Excel VBA/SQL Error on Sharepoint "Cannot update. Database or object is read-only."

I am using ACE.OLEDB inside Excel to run sql and use my sheets like if they are a database.
On my Pc local drive everything works perfectly, but once I upload the file to Sharepoint and launching it from there I am getting the following error :
error number : -2147467259
error description : "Cannot update. Database or object is read-only."
I checked on the net and found some people solving such problem by changing their connection string and adding like IMEX=1 to the extended properties. I tried some suggestions, but it didn't work, maybe I didn't get it well that's why I need your help.
By the way, I do only a Select with my SQL (not an Insert), so I don't know why it needs more than read-only permissions (if any of you can explains it to me), and if manually I try to create a file or folder in the Sharepoint I have no problem with that, that's why I don't think it's a Sharepoint problem.
Here are the rest of parts of the code that may interest you to help me.
I prepare my sql request and call the OpenRecordset which calls the GetConnection function.
sql = "SELECT Distinct Offres FROM ['" & sMySheet & "$'] WHERE Domaine IS NOT NULL AND Domaine = '" & sTempDomaine & "';"
Set rst = OpenRecordset(sql)
The above line will call the OpenRecordset function with the sql request
Public Function OpenRecordset(sql As String) As Object
Const adOpenStatic = 3
Const adLockOptimistic = 3
Const adCmdText = &H1
Set OpenRecordset = CreateObject("ADODB.Recordset")
OpenRecordset.Open sql, GetConnection(), adOpenStatic, adLockOptimistic, adCmdText
End Function
Then OpenRecordset will call the GetConnection and here is where I get the error
Private Function GetConnection() As Object
Dim m_Connection As Object
If m_Connection Is Nothing Then
Set m_Connection = CreateObject("ADODB.Connection")
'Error at the following line
m_Connection.Open "Provider=Microsoft.ACE.OLEDB.12.0;" & _
"Data Source=" & ThisWorkbook.FullName & ";Extended Properties=""Excel 12.0;HDR=Yes;"";"
End If
Set GetConnection = m_Connection
End Function
I get the error precisely at the line of code:
m_Connection.Open "Provider=Microsoft.ACE.OLEDB.12.0;" & _
"Data Source=" & ThisWorkbook.FullName & ";Extended Properties=""Excel 12.0;HDR=Yes;"";"
I hope that any of you may help me to solve this problem
I found a solution to my problem, so I am posting the answer because it may help anyone else, especially that no one provided me an answer.
Based on the comments of Tim Williams, I understood that the problem is not my code itself, but the ThisWorkbook.Fullname that returns the https link of the sharepoint and not a local drive.
Thus, I searched and ended by finding a solution to convert the Http, to local drive, based on the solution here :
I choosed the Solution 2 - Standalone Function (works on Windows and macOS)
Excel's fullname property with OneDrive
On the same time, I had to map a drive of my sharepoint using the microsoft suggested method :
https://support.microsoft.com/en-us/office/map-a-network-drive-to-a-sharepoint-library-751148de-f579-42f9-bc8c-fcd80ccf0f53
Combining both, I solved my problem.
Thanks to anyone who read this question even if couldn't provide me help and thanks to Tim Williams.

Refresh a sql connection file using a single button

I am trying to record a macro to refresh a sql connection file using a single button in vba but it comes up with an error. On hitting the refresh button to which I have assigned the macro, it says
Run time error 91 - You attempted to use an object variable that isn't yet referencing a valid object.
Sub RefreshCRS610()
'
' RefreshCRS610 Macro
'
'
With Selection.ListObject.QueryTable
.Connection = Array( _
"OLEDB;Provider=SQLOLEDB.1;Password=FDReport;Persist Security Info=True;User ID=FDReport;Initial Catalog=M6FDBGRP;Data Source=mlirvcb00" _
, _
"1;Use Procedure for Prepare=1;Auto Translate=True;Packet Size=4096;Workstation ID=FXV10084;Use Encryption for Data=False;Tag w" _
, "ith column collation when possible=False")
.CommandType = xlCmdSql
.CommandText = Array( _
"SELECT DISTINCT OKCONO As 'Company Number', OKCUNO As 'Customer Number', OKSTAT As 'Status', OKRESP As 'Branch Resp" _
, "onsible' FROM M6FDBGRP.MPXFDTA.OCUSMA")
.Refresh BackgroundQuery:=False
End With
End Sub
I was trying to automate refreshing the sql connection table without hitting right click-> edit query->table->okay-> enter pwd again and again. Trying to just refresh the azure sql database table by one click.
Run time error 91 - You attempted to use an object variable that isn't yet referencing a valid object.
Try getting the valid Selection object instance from the Application or ActiveWorksheet instances.

Catching wrong database credentials using VBA to oracle database

I have an Excel-based reporting tool that connects to an oracle database to run canned reports and return the results in a new spreadsheet. I don't have any problem connecting to the database or running my reports. Database credentials are provided via a userform each time a report is needed. I see this question asked in many different ways but no real answer so I'll try to be clear.
Current Behavior
User provides incorrect database credentials
System box pops up with fields for username, password, and server with "Ok" and "Cancel" button
Excel doesn't catch this as an error so I can't use normal error handling.
Desired Behavior
Excel catches the incorrect credentials reported back from the oracle database before the system message pops up
If that happens, I can present the user with my custom error message and branded userform.
I'm just trying to avoid the system message for user experience reasons. Should I try to authenticate with the database and assess the response? Any help would be appreciated! I'm not sure if there is any code I can share that would be helpful.
Updated with a code snippet and workflow:
User click Create Report button
User is presented with userform with 3 dropdowns
User picks application (let's call this variable app) from 1st dropdown
User picks report type (let's call this variable reportType) from 2nd dropdown
User picks report from (let's call this variable report) 3rd dropdown
User clicks Submit button
User provide username and password in second userform
User clicks Submit button
A few things to know about the code snippet below:
dbProvider is OraOLEDB.Oracle.
pw is provided by the user through the userform in step 7.
un is provided by the user through the userform in step 7.
database is stored in the macro itself by application on another tab. The macro looks up the databases for the respective application picked by the user.
wsData is just a tab in my spreadsheet where the result of the query is displayed.
userQuery is created based on the app, reportType, and report picked by the user. I have a few custom functions that build queries based on what the user picked. I don't have any issues with these and they run fine.
This is how Excel connects to the oracle database.
With wsData.ListObjects.Add(SourceType:=0, Source:= _
"OLEDB;Provider=" & dbProvider & ";Password=" & pw & ";User ID=" & un & ";Data Source=" & database, Destination:=wsData.Cells(lrData + 1, 1)).QueryTable
.CommandType = xlCmdSql
.CommandText = userQuery
.RowNumbers = False
.FillAdjacentFormulas = False
.PreserveFormatting = True
.RefreshOnFileOpen = False
.BackgroundQuery = True
.RefreshStyle = xlInsertDeleteCells
.SavePassword = False
.SaveData = True
.AdjustColumnWidth = True
.RefreshPeriod = 0
.PreserveColumnInfo = True
.Refresh BackgroundQuery:=False
End With
This is the box that pops up that I'm trying to keep from popping up:
Oracle Box

VBA - Update Linked Table of an Access file from Excel

I am trying to change the linked table address from an Access file "Hey.accdb" using VBA coding from an Excel file.
I've coded the script below in my Excel file and it prompts the error "Object required" when I run it. Can someone please help me with this problem. I've been staring at it for too long. Thanks.
Sub RunMacroinAccesswithPara2()
Set Db = CreateObject("Access.Application")
Db.OpenCurrentDatabase "D:\Database1\Hey.accdb"
Db.Visible = True
Db.AutomationSecurity = msoAutomationSecurityLow
DoCmd.TransferDatabase TransferType:=acLink, _
DatabaseType:="Microsoft Access", _
DatabaseName:="V:\Reporting\Quarterly\2018Q2\JP\Data\04\Database\Valuation_Database.mdb", _
ObjectType:=acTable, _
Source:="Valuation_Database_Adjusted", _
Destination:="Valuation_Database_Adjusted"
End Sub
DoCmd belongs to the Access application object.
So use
Db.DoCmd.TransferDatabase ' etc.
Edit
To update the link, you need the TableDef object, set its .Connect property and run .RefreshLink.
See Linked table ms access 2010 change connection string

Custom Mapping tool for txt or excel

I have an excel dokument (tab delimitted). Every time before i can insert the excel in my program, i need to map the clients column names to the ones in my app.
So before i begin developing a mapping tool - it would be better if such already existed. But, i don't know i didn't find it.
This tool would actually read an excel or txt file, allow me to name all the names of the new columns on the right and drag and drop (for example).
Maybe this tool has an xml or something where i can define my custom columns, and then it would show op on the right side.
I hope you know what i mean and that someone also had the need for this.
Thanks
info update
I wanted to mention a few things as an update to my question if it's not to late: I have about 50 headers/columns (example: First Name, Middle Name, Street1, Street2,..). So what i always need do every time a client gives me his excel file (contacts backup) is manually copy data for each of his column to the one on my side. And the problem is, every client has different column names, and also some of the columns of the client can go to multiple columns on my side.
So i think, if i can't find a solution, i would make a c++/qt app, which takes an excell and lets me to assign (dragdrop,etc..) every column of his side to on or more columns of my side.
I haven't done any vb programming, so if you can be a bit more detailed about how to aproach the solution i vb that would be great.
Firs part of answer: You can achieve it with a simple vbscript. Copy this code in a vbs extension text file and double click.
Dim oCN As Connection
Dim fs As Scripting.FileSystemObject
Set oCN = New Connection
Set fs = New Scripting.FileSystemObject
sCSVFileName = "C:\Temp\Test1.csv"
sSourceSql = "SELECT field1 as f1, field2 as f2, ... FROM " &
fs.GetFileName(sCSVFileName )
sDestinationTable = "yourAppTable"
With oCN
.Provider = "Microsoft.Jet.OLEDB.4.0"
.Properties("Extended Properties").Value =
"TEXT;HDR=YES;FMT=TabDelimited;MAXSCANROWS=0"
.Open fs.GetFile(sCSVFileName).ParentFolder
End With
sSql = "INSERT INTO [ODBC;DRIVER={SQL Server};Server=" &
ServerName & ";Database=" & DBName & _
IIf(IntegratedSecurity, ";Trusted_Connection=Yes;", _
";UID=" & UID & ";PWD=" & PWD & ";") & _
"]." & sDestinationTable & " " & sSourceSql
oCN.Execute sSql, , adExecuteNoRecords
More info at microsoft social forums
Also, you can parametrize mapping (source and destination tables and mapping fields) with a external xml file.
Second part of answer: You ask if somebody else have this needed and if this is a good idea. Well, this is a very good proposal. And for this reason they are some solutions with this functionality.
First of all, this kind of technology is named ETL. Extract - Transform - Load.
Each database has its own tool
SQL Server Import and Export Wizard
Oracle data pump and loader
etc.
Also exists specific technologies:
SSIS from microsoft.
IBM WebSphere DataStage
etc.
All this tools have mapping columns capabilities.
i use a generic mapping mechanism for that, configured by a couple arrays where you put the names used in your app (aDsNames) with these in your source, the csv file in your case (aDbNames)
I walk the fields in the source, check if the getDbName(name) is in aDsNames and if so write the value in the insertstring to the database.
You can do this both ways, usually my app requests a field to the databasemodule on the server, this module translates to the databasename and does the select.
Hope this is helpfull..
Cheers
select case store
case "store1Midoc"
aDbNames = array("id" , "beheerder", "datumlijst", "rnr13" , "datvan", "dattot", "opmerking", "status" , "waarde", "kode" , "type")
aDsNames = array("id" , "persnr ", "datum ", "rnr13" , "datvan", "dattot", "opmerking", "status" , "waarde", "kode" , "type")
aTypes = array("number", "string", "date" , "string", "date" , "date" , "string" , "number", "number", "string", "string")
case .....
end select
Function getDbName(dsName)
Dim a
getDbName = "undefined"
If instr(join(aDsNames,","),dsName) Then
For a = 0 to UBound(aDbNames)
If aDsNames(a) = dsName Then
getDbName = aDbNames(a)
End If
Next
End If
End Function

Resources