我打开现有的xlsx文件并添加一个新的工作表。然后我只想保存文件。
Dim wb As Workbook
Dim ws As Worksheet
Set wb = Workbooks.Open(fileName:=pathToFile, Editable:=True, ReadOnly:=False)
Set ws = wb.Worksheets.Add()
ws.Name = "newSheet"
ws.range("A1").CopyFromRecordset rs
wb.Save
wb.Close
但是wb.Save将文件保存到$ USERS \ Documents,尽管它不是我打开文件的源目录。
为什么vba会这样做?
我也尝试了wb.SaveAs pathToFile,但这导致了一个错误。 并且wb.Close SaveChanges:= True也不起作用。
我需要将此文件保存到相同的路径和名称。
当然我可以做wb.SaveAs pathToFile& " _tmp",删除旧文件并重命名新文件。但是为什么Save不工作?
修改
Dim strCon As String: strCon = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=path\file.xlsx;Mode=Read;Extended Properties=""Excel 12.0;HDR=Yes;IMEX=1"";"
Dim sql as String
Dim cn As ADODB.Connection
Dim rs As ADODB.Recordset
Set cn = CreateObject("ADODB.Connection")
Set rs = CreateObject("ADODB.Recordset")
cn.Open strCon
rs.Open Source:=sql, ActiveConnection:=cn
Dim wb As Workbook
Dim ws As Worksheet
Set wb = Workbooks.Open(fileName:=path\file.xlsx, ReadOnly:=False)
Set ws = wb.Worksheets.Add()
ws.Range("A1").CopyFromRecordset rs
rs.Close
cn.Close
wb.Save
wb.Close
答案 0 :(得分:0)
经过几个小时的努力和Oscar的不懈支持(请参阅评论。非常感谢!)此问题的解决方案是加载here(感谢Oscar)中建议的工作簿。然而,工作簿将以ReadOnly的形式打开。要更改此设置,只需通过设置wb.ChangeFileAccess xlReadWrite来更改FileAccess模式。
上面的代码现在看起来像这样:
Dim strCon As String: strCon = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=path\file.xlsx;Mode=Read;Extended Properties=""Excel 12.0;HDR=Yes;IMEX=1"";"
Dim sql as String
Dim cn As ADODB.Connection
Dim rs As ADODB.Recordset
Set cn = CreateObject("ADODB.Connection")
Set rs = CreateObject("ADODB.Recordset")
cn.Open strCon
rs.Open Source:=sql, ActiveConnection:=cn
Dim wb As Workbook
Dim ws As Worksheet
Workbooks.Open Filename:=file.xlsx ' <-- Look here
Set wb = Workbooks("file.xlsx") ' <-- And here
Set ws = wb.Worksheets.Add()
ws.Range("A1").CopyFromRecordset rs
rs.Close
cn.Close
wb.ChangeFileAccess xlReadWrite ' <-- And here
wb.Save
wb.Close
但是,如果省略wb.ChangeFileAccess xlReadWrite
,仍然不清楚为什么vba会将工作簿的路径更改为用户文档目录。
修改强>
在重构我的代码时,我发现了更多有关使用WorkBook.ChangeFileAccess
的内容。如果在同一个Sub中创建ADODB.Connection
,则必须将文件访问权限更改为xlReadWrite,如上所述。但是如果你写了一个函数来传递连接字符串和要执行的sql查询然后创建ADODB连接,那么更改工作簿的文件访问将导致错误。
示例:
Public Function ExecSql(conn as String, sql as String) As Recordset
Dim recSet As Recordset
Dim cn As ADODB.Connection
Dim rs As ADODB.Recordset
Set cn = CreateObject("ADODB.Connection")
cn.Mode = adModeReadWrite
cn.Open conn
Set rs = CreateObject("ADODB.Recordset")
rs.Open Source:=sql, ActiveConnection:=cn
Set recSet = rs
Set ExecQuery = recSet
End function
在调用Sub:
Dim conn As String: conn = "" ' connection String, see above
Dim sql As String: sql = "" ' the query
' Open workbook here like above
Dim rs As Recordset: Set rs = ExecSql(strCon, sql)
ws.Range("A1").CopyFromRecordset rs
rs.Close
' wb.ChangeFileAccess xlReadWrite ' not needed
wb.Save
wb.Close
不要忘记在调用sub中调用rs.Close
而不是在ExecSql函数中调用(参见第2和第3个答案here)
另一件事:你必须在打开工作簿后调用ExecSql。如果执行ExecSql之前它不会保存更改。