vba Workbook.Save 保存到不同目录
vba Workbook.Save saves to different directory
我打开一个现有的 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",删除旧文件并重命名新文件。但是为什么保存不起作用?
编辑
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
经过数小时的尝试和 Oscar 的不懈支持(请参阅评论。非常感谢!),此问题的解决方案是按照 here 中的建议加载工作簿(感谢 Oscar)。尽管如此,工作簿将以只读方式打开。要更改此设置,只需通过设置 wb.ChangeFileAccess xlReadWrite.
更改文件访问模式
上面的代码现在看起来像这样:
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
并且在调用子中:
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 而不是在 ExecSql 函数中调用 rs.Close
(参见第二和第三个答案 here)
另一件事:您必须在打开工作簿后调用 ExecSql。如果之前执行了 ExecSql,它不会保存更改。
我打开一个现有的 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",删除旧文件并重命名新文件。但是为什么保存不起作用?
编辑
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
经过数小时的尝试和 Oscar 的不懈支持(请参阅评论。非常感谢!),此问题的解决方案是按照 here 中的建议加载工作簿(感谢 Oscar)。尽管如此,工作簿将以只读方式打开。要更改此设置,只需通过设置 wb.ChangeFileAccess xlReadWrite.
更改文件访问模式上面的代码现在看起来像这样:
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
.
编辑
在重构我的代码时,我观察到更多关于 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
并且在调用子中:
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 而不是在 ExecSql 函数中调用 rs.Close
(参见第二和第三个答案 here)
另一件事:您必须在打开工作簿后调用 ExecSql。如果之前执行了 ExecSql,它不会保存更改。