如何阻止 OLEDB 自动创建“(sheet name)1”sheet
How to stop OLEDB to create "(sheet name)1" sheet automatically
背景
我正在编写一个 PowerShell 脚本,将一些数据写入 Excel 文件 (.xlsx
),其中 Microsoft.ACE.OLEDB
如下所示:
$fileName = "C:\tmp\createtest.xlsx"
$sheetName = "record"
$provider = "Provider=Microsoft.ACE.OLEDB.12.0"
$dataSource = "Data Source = $fileName"
$extend = "Extended Properties=Excel 12.0"
$ddlSQL = "CREATE TABLE [$sheetName] (ID CHAR(4), NAME VARCHAR(20))"
$conn = New-Object System.Data.OleDb.OleDbConnection("$provider;$dataSource;$extend")
$sqlCommand = New-Object System.Data.OleDb.OleDbCommand
$sqlCommand.Connection = $conn
$conn.open()
$sqlCommand.CommandText = $ddlSQL
$sqlCommand.ExecuteNonQuery()
...
$conn.close()
问题
当您手动创建带有名为 record
的空 sheet 的 C:\tmp\createtest.xlsx
时,CREATE TABLE
语句会自动创建 record1
sheet。
我想停止这种行为,让 CREATE TABLE
语句像普通 RDBMS 一样抛出异常。
问题
当 Excel 文件有一个同名的 sheet 时,有什么方法可以阻止 OLEDB 自动创建 (sheet name)1
sheet 吗?
我找到了解决办法。执行 CREATE TABLE
后缀 $
for table name:
$ddlSQL = "CREATE TABLE [${sheetName}$] (ID CHAR(4), NAME VARCHAR(20))"
如果书和 sheet record
已经存在,则此语句将无误地完成。如果这本书或 sheet record
不存在,该语句将抛出 OleDbException
。无论哪种方式,都不会创建新的 sheet,因此您可以安全地测试 sheet 的存在。
如果你想使用 sheet record
而不管现有的 sheet 并避免自动创建 record1
sheet,你可以这样做这个:
$checkExistenceSQL = "CREATE TABLE [${sheetName}$] (ID CHAR(4), NAME VARCHAR(20))"
$ddlSQL = "CREATE TABLE [$sheetName] (ID CHAR(4), NAME VARCHAR(20))"
$conn.open()
try {
try {
# Check existing sheet and open if it exists
$sqlCommand.CommandText = $checkExistenceSQL
$sqlCommand.ExecuteNonQuery() > $null
} catch {
try {
# Create new sheet if it doesn't exist
$sqlCommand.CommandText = $ddlSQL
$sqlCommand.ExecuteNonQuery() > $null
} catch {
throw $PSItem
}
}
$insertSQL = "INSERT INTO [${sheetName}$] VALUES (...)"
$sqlCommand.CommandText = $insertSQL
$sqlCommand.ExecuteNonQuery() > $null
} finally {
$conn.close()
}
请注意,即使 sheet 已经存在,您也必须先执行 CREATE TABLE
,因为它会影响数据类型约束的有效性。此外,您必须在 INSERT
语句中为 table 名称加上 $
后缀,因为如果 sheet record
已经存在,它将失败。有关详细信息,请参阅 https://satob.hatenablog.com/entry/2021/11/24/003818 and https://satob.hatenablog.com/entry/2021/11/25/012835。
背景
我正在编写一个 PowerShell 脚本,将一些数据写入 Excel 文件 (.xlsx
),其中 Microsoft.ACE.OLEDB
如下所示:
$fileName = "C:\tmp\createtest.xlsx"
$sheetName = "record"
$provider = "Provider=Microsoft.ACE.OLEDB.12.0"
$dataSource = "Data Source = $fileName"
$extend = "Extended Properties=Excel 12.0"
$ddlSQL = "CREATE TABLE [$sheetName] (ID CHAR(4), NAME VARCHAR(20))"
$conn = New-Object System.Data.OleDb.OleDbConnection("$provider;$dataSource;$extend")
$sqlCommand = New-Object System.Data.OleDb.OleDbCommand
$sqlCommand.Connection = $conn
$conn.open()
$sqlCommand.CommandText = $ddlSQL
$sqlCommand.ExecuteNonQuery()
...
$conn.close()
问题
当您手动创建带有名为 record
的空 sheet 的 C:\tmp\createtest.xlsx
时,CREATE TABLE
语句会自动创建 record1
sheet。
我想停止这种行为,让 CREATE TABLE
语句像普通 RDBMS 一样抛出异常。
问题
当 Excel 文件有一个同名的 sheet 时,有什么方法可以阻止 OLEDB 自动创建 (sheet name)1
sheet 吗?
我找到了解决办法。执行 CREATE TABLE
后缀 $
for table name:
$ddlSQL = "CREATE TABLE [${sheetName}$] (ID CHAR(4), NAME VARCHAR(20))"
如果书和 sheet record
已经存在,则此语句将无误地完成。如果这本书或 sheet record
不存在,该语句将抛出 OleDbException
。无论哪种方式,都不会创建新的 sheet,因此您可以安全地测试 sheet 的存在。
如果你想使用 sheet record
而不管现有的 sheet 并避免自动创建 record1
sheet,你可以这样做这个:
$checkExistenceSQL = "CREATE TABLE [${sheetName}$] (ID CHAR(4), NAME VARCHAR(20))"
$ddlSQL = "CREATE TABLE [$sheetName] (ID CHAR(4), NAME VARCHAR(20))"
$conn.open()
try {
try {
# Check existing sheet and open if it exists
$sqlCommand.CommandText = $checkExistenceSQL
$sqlCommand.ExecuteNonQuery() > $null
} catch {
try {
# Create new sheet if it doesn't exist
$sqlCommand.CommandText = $ddlSQL
$sqlCommand.ExecuteNonQuery() > $null
} catch {
throw $PSItem
}
}
$insertSQL = "INSERT INTO [${sheetName}$] VALUES (...)"
$sqlCommand.CommandText = $insertSQL
$sqlCommand.ExecuteNonQuery() > $null
} finally {
$conn.close()
}
请注意,即使 sheet 已经存在,您也必须先执行 CREATE TABLE
,因为它会影响数据类型约束的有效性。此外,您必须在 INSERT
语句中为 table 名称加上 $
后缀,因为如果 sheet record
已经存在,它将失败。有关详细信息,请参阅 https://satob.hatenablog.com/entry/2021/11/24/003818 and https://satob.hatenablog.com/entry/2021/11/25/012835。