Arrays 可以从变量创建PS自定义对象吗?
我在sql server中有一个100列的表,我想使它成为一个不需要在文件中传递所有列来加载的表。我在一个表中指定了列名,然后比较哈希表中的列以找到匹配的列。然后,根据要用于插入文件中数据的数组的匹配创建代码。问题是,它不喜欢调用一个变量来创建自定义对象 我将以下内容存储在一个数组中。例如,在其中的100个示例中,下面的示例通知sqlcolumn2被跳过 sqlcolumn1=if[string]::IsNullOrEmpty$obj.P1-eq$true{$null}else{$obj.P1} sqlcolumn3=if[string]::IsNullOrEmpty$obj.P2-eq$true{$null}else{$obj.P2} sqlcolumn4=if[string]::IsNullOrEmpty$obj.P3-eq$true{$null}else{$obj.P3} sqlcolumn5=if[string]::IsNullOrEmpty$obj.P4-eq$true{$null}else{$obj.P4} 以下是阵列:Arrays 可以从变量创建PS自定义对象吗?,arrays,powershell,pscustomobject,Arrays,Powershell,Pscustomobject,我在sql server中有一个100列的表,我想使它成为一个不需要在文件中传递所有列来加载的表。我在一个表中指定了列名,然后比较哈希表中的列以找到匹配的列。然后,根据要用于插入文件中数据的数组的匹配创建代码。问题是,它不喜欢调用一个变量来创建自定义对象 我将以下内容存储在一个数组中。例如,在其中的100个示例中,下面的示例通知sqlcolumn2被跳过 sqlcolumn1=if[string]::IsNullOrEmpty$obj.P1-eq$true{$null}else{$obj.P1}
foreach($line in $Final)
{
$DataRow = "$($line."TableColumnName") = if ([string]::IsNullOrEmpty(`$obj.$($line."PName")) -eq `$true) {`$null} else {`"`$obj.$($line."PName")`"}"
$DataArray += $DataRow
}
然后,我尝试将它添加到一个最终数组中,在该数组中,我希望它对每一行数据进行循环,然后从数组中执行插入。即使上面数组中的字符串值是正确的,如果它是手工编码的,我也无法让它识别行并运行
foreach ($obj in $data2)
{
$test = [PSCustomObject] @{
$DataArray = Invoke-Expression $DataArray
}
如果我只是键入$DataArray,它不喜欢这样,因为它需要我已经内置到字符串中的=符号
这是我想做的,甚至是可能的
我试图用各种不同的方式来获取这些数据,有些人向我们发送了100列中的30列,其他的或多或少,没有人使用精确的列来减少每件事的单个脚本
添加更多代码:
Function ArrayCompare() {
[CmdletBinding()]
PARAM(
[Parameter(Mandatory=$True)]$Array1,
[Parameter(Mandatory=$True)]$A1Match,
[Parameter(Mandatory=$True)]$Array2,
[Parameter(Mandatory=$True)]$A2Match)
$Hash = @{}
foreach ($Data In $Array1) {
$Hash[$Data.$A1Match] += ,$Data
}
foreach ($Data In $Array2) {
$Hash[$Data.$A2Match] += ,$Data
}
foreach ($KeyValue In $Hash.GetEnumerator()){
$Match1, $Match2 = $KeyValue.Value.Where( {$_.$A1Match}, 'Split')
[PSCustomObject]@{
MatchValue = $KeyValue.Key
A1Matches = $Match1.Count
A2Matches = $Match2.Count
TablePosition = [int]$Match2.TablePosition
TableColumnName = $Match2.TableColumnName
# PName is the P(##) that is a generic ascending column value back to import-excel module. ColumnA = P1, ColumnB = P2 etc..until no data is detected. Allows flexibility and not having to know how many columns there are
PName = $Match1.Name}
}
}
$Server = 'ServerName'
$Catalog = 'DBName'
$DestinationTable = 'ImportIntoTableName'
$FileIdentifierID = 10
$FileName = 'Test.xlsx'
$FilePath = 'C:\'
$FullFilePath = $FilePath + $FileName
$data = Import-Excel -Path $FullFilePath -NoHeader -StartRow 1 # Import-
Excel Module for working with xlsx excel files
$data2 = Import-Excel -Path $ullFilePath -NoHeader -StartRow 2 # Import-
Excel Module for working with xlsx excel files
$ExpectedHeaderArray = @()
$HeaderArray = @()
$DataArray = @()
$HeaderDetect = @()
$HeaderDetect = $data | Select-Object -First 1 # Header Row In File
$HeaderDetect |
ForEach-Object {
$ColumnValue = $_
$ColumnValue |
Get-Member -MemberType *Property |
Select-Object -ExpandProperty Name |
ForEach-Object {
$HeaderValues = [PSCustomObject]@{
Name = $_
Value = $ColumnValue.$_}
$HeaderArray += $HeaderValues
}
}
# Query below provides a list of all expected file headers and the table
column name they map to
$Query = "SELECT TableColumnName, FileHeaderName, TablePosition FROM
dbo.FileHeaders WHERE FileIdentifierID = $($FileIdentifierID)"
$ds = Invoke-Sqlcmd -ServerInstance $Server -Database $Catalog -Query $Query
-OutputAs DataSet
$ExpectedHeaderArray = foreach($Row in $ds.Tables[0].Rows)
{
new-object psObject -Property @{
TableColumnName = "$($row.TableColumnName)"
FileHeaderName = "$($row.FileHeaderName)"
TablePosition = "$($row.TablePosition)"
}
}
#Use Function Above
#Bring it together so we know what P(##) goes with which header in file/mapped to table column name
$Result = ArrayCompare -Array1 $HeaderArray -A1Match Value -Array2 $ExpectedHeaderArray -A2Match FileHeaderName
$Final = $Result | sort TablePosition
foreach($Line in $Final)
{
$DataRow = "$($Line."TableColumnName") = if ([string]::IsNullOrEmpty(`$obj.$($Line."PName")) -eq `$true) {`$null} else {`"`$obj.$($Line."PName"))`"}"
$DataArray += $DataRow
}
# The output below is what the code inside the last array would be that I would use to import into excel.
# The goal is to be dynamic and match headers in the file to the stored header value and import into a table (mapped from header column to table column name)
# The reason for this is before I was here, there were many different "versions" of a layout that was given out. In the end, it is all one in the same
# but some send all 100 columns, some only send a handful, some send 80 etc. I am trying to have everything flow through here vs. 60+ pieces of code/stored procedures/ssis packs
Write-Output $DataArray
# Output Sample -- Note how in the sample, P2 and subsequent skip SQLColumn2 because P2 maps to the header value of position 3 in the sql table and each after is one off.
# In this example, SqlColumn2 would not be populated
# SqlColumn1 = if ([string]::IsNullOrEmpty($obj.P1) -eq $true) {$null} else {"$obj.P1"}
# SqlColumn3 = if ([string]::IsNullOrEmpty($obj.P2) -eq $true) {$null} else {"$obj.P2"}
# SqlColumn4 = if ([string]::IsNullOrEmpty($obj.P3) -eq $true) {$null} else {"$obj.P3"}
# SqlColumn5 = if ([string]::IsNullOrEmpty($obj.P4) -eq $true) {$null} else {"$obj.P4"}
# I know this doesn't work. This is where I'm stuck, how to build an array now off of this output from above
foreach ($obj in $data2)
{
$test = [PSCustomObject] @{
$DataArray = Invoke-Expression $DataArray}
}
我想先重新陈述一下你的问题,只是为了确保我能正确理解,我可能不理解 您得到的excel文件如下所示: 您还有一个数据库表,如下所示: 还有一个列映射表,如下图所示,ColumnX在本例中未映射: 您希望使用映射表中的数据将电子表格中的值插入到数据库表中,以便获得以下结果: 因此,让我们加载电子表格,让标题行这次生成有意义的属性名称: $data=导入Excel-路径。\MySpreadsheet.xlsx; 写入主机$data | ft | out字符串; 校长 ---- ---- ---- P值Q值R 值S值T值U 获取列映射数据我正在以编程方式创建内存中的数据集,但显然您是从数据库中读取数据的: $mappings=新对象System.Data.DataTable; $null=$mappings.Columns.AddTableColumnName,[string]; $null=$mappings.Columns.AddFileHeaderName,[string]; $null=$mappings.Columns.AddTablePosition,[int]; @ @{TableColumnName=ColumnW;FileHeaderName=HeaderA;TablePosition=1}, @{TableColumnName=ColumnY;FileHeaderName=HeaderB;TablePosition=2}, @{TableColumnName=ColumnZ;FileHeaderName=HeaderC;TablePosition=3} | % { $row=$mappings.NewRow; $row.TableColumnName=$\ TableColumnName; $row.FileHeaderName=$\ux.FileHeaderName; $row.TablePosition=$\表位置; $mappings.Rows.添加$row; } $ds=新对象System.Data.DataSet; $ds.Tables.Add$mappings; 写入主机$ds.Tables[0]| ft | out字符串 TableColumnName文件标题名称TablePosition -------- ------- ------- 专栏W标题1 柱状封头B 2 ColumnZ HeaderC 3 现在,我们可以构建映射对象: $values=@; $data中的foreach$行 { $properties=[ordered]@{}; $mappings中的foreach$mapping { $properties.Add$mapping.TableColumnName,$row.$$mapping.FileHeaderName; } $values+=新对象PSCustomObject-属性$properties; } 写入主机$values | ft | out字符串 圆柱 ---- ---- ---- P值Q值R 值S值T值U 棘手的是$properties。添加$mapping.TableColumnName,$row.$$mapping.FileHeaderName;-基本上,您可以使用虚线字符串文字或变量访问PowerShell中的对象属性,我不确定确切的功能名称-例如 PS>$myValue=新对象PSCustomObject-Property@{aaa=bbb;ccc=ddd} PS>$myValue.aaa bbb PS>$myProperty=aaa PS>$myValue.$myProperty bbb 因此,$row.$$mapping.FileHeaderName是一个表达式,其计算结果为$mapping.FileHeaderName中命名的$row属性的值 最后,您可以使用现有进程将对象插入数据库 请注意,我无法完全了解您的ArrayCompare实际上在做什么,因此上述方法可能无法100%解决您的问题,但希望您可以自己解决差异,或者留下与所需解决方案不同之处的注释
希望这能有所帮助。我认为你想做的事情可能是可以做到的,而且大多数情况下
kely不需要构建一个代码字符串来调用调用调用表达式,这可能是不安全的,但是查看i您的输入文件的示例以及如何加载它ii您的映射哈希表iii的示例$DataArray的结果示例会很有用。也许把你的例子缩减到5列而不是100列……我在原来的问题中添加了一些代码,希望这能有所帮助。我不知道为什么格式化被关闭,因为我的代码阻止了整个部分。我正在为映射到Sql表列名的每个文件提取预先确定的列名。希望这是有意义的。可能是杀伤力太大了。如果您需要一个文件,请告诉我……如果不构建SQL列映射表,就很难创建一个文件。谢谢@麦克莱顿
+---+---------+---------+---------+
| | A | B | C |
+---+---------+---------+---------+
| 1 | HeaderA | HeaderB | HeaderC |
+---+---------+---------+---------+
| 2 | Value P | Value Q | Value R |
+---+---------+---------+---------+
| 3 | Value S | Value T | Value U |
+---+---------+---------+---------+
+---------+---------+---------+---------+
+ ColumnW | ColumnX | ColumnY | ColumnZ |
+---------+---------+---------+---------+
+ ....... | ....... | ....... | ....... |
+---------+---------+---------+---------+
+-----------------+----------------+---------------+
| TableColumnName | FileHeaderName | TablePosition |
+-----------------+----------------+---------------+
| ColumnW | HeaderA | 1 |
+-----------------+----------------+---------------+
| ColumnY | HeaderB | 2 |
+-----------------+----------------+---------------+
| ColumnZ | HeaderC | 3 |
+-----------------+----------------+---------------+
+---------+---------+---------+---------+
+ ColumnW | ColumnX | ColumnY | ColumnZ |
+---------+---------+---------+---------+
+ Value P | null | Value Q | Value R |
+---------+---------+---------+---------+
+ Value S | null | Value T | Value U |
+---------+---------+---------+---------+