我一直在尝试将以下代码从SQL Server转换为直接从Excel VBA运行。但无法这样做。
Update Legal
Set Category = Case
when datediff(month, GETDATE(), [End date]) > 9
then 'Blue'
when datediff(month, GETDATE(), [End date]) < 9
and datediff(month, GETDATE(), [end date]) > 1
then 'Orange'
when datediff(month, GETDATE(), [End date]) < 2
then 'Red'
End
where classification = 'A'
Select
classification,
datediff(month, GETDATE(), [End date]),
Category
from
Legal
如下所示进入VBA
Dim Cn As ADODB.Connection
Dim Server_Name As String
Dim Database_Name As String
Dim User_ID As String
Dim Password As String
Dim SQLSelect As String
Dim rs As ADODB.Recordset
Dim sqlcmd as string
cbb = Environ("computername")
With Sheet3.Range("A4:Z" & Rows.Count)
.ClearContents
'.ClearFormats
End With
sqlcmd = "Update Legal Set Category = Case" & _
" when datediff(month,GETDATE(),[End date])>9 then 'Blue'" & _
" when datediff(month,GETDATE(),[End date])<9 and datediff(month,GETDATE(),[end date])>1 then 'Orange'" & _
" when datediff(month,GETDATE(),[End date])<2 then 'Red'" & _
" End " & _
" where classification = 'A'"
Debug.Print sqlcmd
With Sheet3.ListObjects.Add(SourceType:=0, Source:=Array( _
"OLEDB;Provider=SQLOLEDB.1;Persist Security Info=True;User ID=Login_ID;Password=Password;Data Source=Server_Name;Use Procedure f" _
, _
"or Prepare=1;Auto Translate=True;Packet Size=4096;Workstation ID=" & cbb & ";Use Encryption for Data=False;Tag with column collatio" _
, "n when possible=False;Initial Catalog=DB_Name"), Destination:=Sheet3.Range( _
"$A$4")).QueryTable
.CommandType = xlCmdSql
.CommandText = sqlcmd
.RowNumbers = False
.FillAdjacentFormulas = False
.PreserveFormatting = True
.RefreshOnFileOpen = False
.BackgroundQuery = True
.RefreshStyle = xlInsertDeleteCells
.SavePassword = False
.SaveData = True
.AdjustColumnWidth = True
.RefreshPeriod = 0
.PreserveColumnInfo = True
.SourceConnectionFile = _
"C:\Users\xxxxx\Documents\My Data Sources\xxxxx.odc"
.ListObject.DisplayName = _
"AP_123"
.Refresh BackgroundQuery:=False
End With
此查询在SQL Server中完全有效。但是我在VBA中遇到以下错误:
查询未运行,或无法打开数据库表。
检查数据库服务器或与数据库管理员联系。确保外部数据库可用且尚未移动或重组,然后再次尝试操作。
请帮助我们!!几个星期以来一直试着这个!
P.S。不需要Power Query,因为它会向无权访问服务器的其他用户请求凭据
答案 0 :(得分:1)
如上所述,只需首先实际运行action UPDATE
语句,然后将QueryTable连接到SELECT
语句,即可将两个查询分开。您甚至可以缩短 Source 参数中的连接字符串:
Dim Cn As ADODB.Connection, rs As ADODB.Recordset
Dim Server_Name As String, Database_Name As String
Dim User_ID As String, Password As String
Dim conn_str As String, SQLSelect As String, sqlcmd as string
cbb = Environ("computername")
With Sheet3.Range("A4:Z" & Rows.Count)
.ClearContents
'.ClearFormats
End With
conn_str = "Provider=SQLOLEDB.1;Persist Security Info=True;User ID=Login_ID;Password=Password;" & _
"Data Source=Server_Name;Use Procedure for Prepare=1;Auto Translate=True;" & _
"Packet Size=4096;Workstation ID=" & cbb & ";Use Encryption for Data=False;" & _
"Tag with column collation when possible=False;Initial Catalog=DB_Name"
Cn.Open conn_str
' EXECUTE ACTION QUERY
sqlcmd = "UPDATE Legal SET Category = Case" & _
" when datediff(month,GETDATE(),[End date])>9 then 'Blue'" & _
" when datediff(month,GETDATE(),[End date])<9 and " & _
" datediff(month,GETDATE(),[end date])>1 then 'Orange'" & _
" when datediff(month,GETDATE(),[End date])<2 then 'Red'" & _
" End " & _
" where classification = 'A'"
Cn.Execute sqlcmd
' CONNECT TO SELECT QUERY
sqlcmd = "SELECT classification, datediff(month, GETDATE(), [End date]), Category " & _
" FROM Legal;"
With Sheet3.ListObjects.Add(SourceType:=0, Source:=Array( _
"OLEDB;" & conn_str), Destination:=Sheet3.Range( _
"$A$4")).QueryTable
.CommandType = xlCmdSql
.CommandText = sqlcmd
.RowNumbers = False
.FillAdjacentFormulas = False
.PreserveFormatting = True
.RefreshOnFileOpen = False
.BackgroundQuery = True
.RefreshStyle = xlInsertDeleteCells
.SavePassword = False
.SaveData = True
.AdjustColumnWidth = True
.RefreshPeriod = 0
.PreserveColumnInfo = True
.SourceConnectionFile = _
"C:\Users\xxxxx\Documents\My Data Sources\xxxxx.odc"
.ListObject.DisplayName = _
"AP_123"
.Refresh BackgroundQuery:=False
End With
Cn.Close
Set Cn = Nothing
答案 1 :(得分:1)
这是存储过程方法。在SSMS中,运行一次
CREATE PROCEDURE dbo.UpdateAndGetLegal
AS
UPDATE Legal
SET Category = CASE WHEN DATEDIFF(MONTH, GETDATE(), [End date]) > 9 THEN 'Blue'
WHEN DATEDIFF(MONTH, GETDATE(), [End date]) < 9
AND DATEDIFF(MONTH, GETDATE(), [end date]) > 1 THEN 'Orange'
WHEN DATEDIFF(MONTH, GETDATE(), [End date]) < 2 THEN 'Red'
END
WHERE classification = 'A'
SELECT classification
, DATEDIFF(MONTH, GETDATE(), [End date])
, Category
FROM Legal
这将创建一个运行更新并返回SELECT结果的存储过程。
在Excel中,我几乎不需要.Add
一个ListObject。有时我必须更改现有ListObject的SQL语句,但是一旦创建了表,就不需要再次创建它。所以我不完全确定你在做什么,但这是我的一个项目的样子。
我创建了一个Excel文件(或模板,如果它是我正在生成的东西)。在该文件中,我创建了一个外部数据ListObject,其命令文本为
EXEC UpdateAndGetLegal
然后,如果用户只是刷新表,我就完成了。如果我需要我的代码刷新表,那就是
Sheet3.ListObjects(1).QueryTable.Refresh
如果您将Windows凭据传递给SQL Server,则所有用户都需要存储过程的EXECUTE权限。
答案 2 :(得分:0)
我在这里做了一些猜测,但这是基于感觉不适的东西。
每次运行SELECT以获取一些数据
Select
classification,
datediff(month, GETDATE(), [End date]),
Category
from
Legal
您首先运行UPDATE ...
Update Legal
Set Category = Case
when datediff(month, GETDATE(), [End date]) > 9
then 'Blue'
when datediff(month, GETDATE(), [End date]) < 9
and datediff(month, GETDATE(), [end date]) > 1
then 'Orange'
when datediff(month, GETDATE(), [End date]) < 2
then 'Red'
End
where classification = 'A'
这很奇怪,我想不出任何适用于任何数据库的用例。相反,你可以自己选择SELECT:
Select
classification,
datediff(month, GETDATE(), [End date]),
Case WHEN classification = 'A'
THEN
CASE
when datediff(month, GETDATE(), [End date]) > 9
then 'Blue'
when datediff(month, GETDATE(), [End date]) < 9
and datediff(month, GETDATE(), [end date]) > 1
then 'Orange'
when datediff(month, GETDATE(), [End date]) < 2
then 'Red'
End
ELSE Category
END
from
Legal
这是做同样的事情,但没有触及Legal
中的基础数据。这个SELECT是您想要偷偷摸摸进入VBA / QueryTable的那个。