将Excel数据导入PowerShell变量

时间:2014-04-04 16:20:52

标签: powershell

我有一个Excel文件,其中包含未知数量的记录,以及这3列: 变量名称,商店编号,电子邮件地址

我在QlikView中使用它来导入某些商店的数据,然后为列表中的每个商店创建一个单独的报告。然后,我需要将每个报告通过电子邮件发送到每个商店(商店编号将在报告文件名中)。

所以在PowerShell中我想阅读Excel文件并为每个商店设置变量:

$Store1 = The Store Number in Row 2 of the Excel File  
$Store1Email = The Store Email in Row 2 of the Excel File  
$Store2 = The Store Number in Row 3 of the Excel File  
$Store2Email = The Store Email in Row 3 of the Excel File  
etc. for each Storein the file (can be any number of stores).  

有人可能会帮忙吗?请注意"变量名称"必须忽略excel文件中的内容(对于QLikView),并且必须按照上面的示例命名PowerShell变量,每次都增加数字。

6 个答案:

答案 0 :(得分:3)

查看我的PowerShell Excel模块on Github。您还可以grab it from the PowerShell Gallery.

$stores = Import-Excel C:\Temp\store.xlsx

$stores[2].Name
$stores[2].StoreNumber
$stores[2].EmailAddress

''
'All stores'
'----------'
$stores

enter image description here

答案 1 :(得分:2)

好的,首先,如果您要使用实际的.XLS或.XLSX或.XLSM文件,我强烈建议您使用TechNet库中的Import-XLS函数(found here)。

之后,只需引用它导入的对象来发送电子邮件,而不是为每个商店制作对象。如:

$StoreList = Import-XLS <path to Excel file>
GC <report folder> | %{
    $Current = $_
    $Store = $StoreList|?{$_.StoreNumber -match $Current.BaseName}|Select -ExpandProperty StoreNumber
    $Email = $StoreList|?{$_.StoreNumber -match $Current.BaseName}|Select -ExpandProperty StoreEmail
    <code to send $Current to $Email>
}

答案 2 :(得分:0)

在这里原谅丑陋。我不是程序员,所以毫无疑问会有更优化的方法来实现这一点,以及更好的格式化。但是,如果我正确理解您的要求,它将会起作用。

$excelfile = import-csv "c:\myfile.csv"
$i = 1
$excelfile | ForEach-Object {
    New-Variable "Store$i" $_."Store Number"
    $iemail = $i.ToString() + "Email"
    New-Variable "Store$iemail" $_."Email Address"
    $i ++
    }

编辑:根据对原始帖子的回复,这适用于csv文件。如有必要,请先将其保存到csv。

答案 3 :(得分:0)

我的偏好是将Excel文件另存为'.csv'类型。可以轻松地将逗号分隔值导入PowerShell。

$csvFile = Import-Csv -Path c:\scripts\temp\excelFile.csv
#now the entire Excel '.csv' file is saved into csvFile variable

$csvFile |Get-Member
#look at the properties

请记住研究这些伟大的东西,以便您的PowerShell脚本看起来很棒。 Jeffery Snover,Jason Hicks,Don Jones,Ashley McGlone和他们朋友名单上的任何人都哈哈

答案 4 :(得分:0)

$excelfile = import-csv "C:\Temp\store.csv"

$i = 1 $excelfile | ForEach-Object {
    $NA= $_."Name"
    $SN= $_."StoreNumber"
    Write-Output "row $i"
    $NA
    $SN

    $i++ }

答案 5 :(得分:0)

上面的答案通常有效,但是我刚有一个包含excel数据表的项目,这导致了一些问题。

edit:这是一个更高级的版本,它将把它放入对象中,可以处理空白和重复的列名,并且可以通过在标题行中查找内容来跳过工作表开头的人员信息。我还提供了一些示例用法

您的示例:

$file = New-Module -AsCustomObject -ScriptBlock $file_template
$file.from_excel("c:\folder\file.xls")
$Store1      = $file.data[0]."Store Number" #first row, column named "Store Number"
$Store1Email = $file.data[0]."Store Email"  #first row, column named "Store Email"
foreach ($row in $file.data)
{
    write-host "Store:       $($row."Store Number")"
    write-host "Store Email: $($row."Store Email")"
}

示例1:

# Simplest example
$file = New-Module -AsCustomObject -ScriptBlock $file_template
$file.from_excel("c:\folder\file.xls")
$file.data[0]

示例2:

#advanced usage
$file = New-Module -AsCustomObject -ScriptBlock $file_template
$file.header_contains="First Name" # if included it will drop everything before the first line that contains this, useful if there are instructions for humans in the worksheet
$file.indexer_column = 5 # Default: 1 (first column); This column's contents will set the minimum number of rows, use if there are blank rows in your file but more data after them
$file.worksheet_index = "January" # Default: 1; can be a sheet index or sheet name
$file.filename = "c:\folder\file.xls" #can set this independently, useful for validation and troubleshooting
$file.from_excel() #This is where we actually pull from excel
$collected = $file.data|ogv -pass thru #this is a neat way to select some rows you want
$file.headers.count # It stores an array of the headers here, useful for troubleshooting and advanced logic

Excel Reader伪类

$file_template = {

    # -- universal --
    $filename = ""
    $delimiter = ","
    $headers = @()
    $data = @()

    # -- used by some functions --
    # we put these here to allow assigning them before calling functions, which improves readability and auditability
    $header_contains=""
    $indexer_column=1
    $worksheet_index=1

    function from_excel(
        $filename=$this.filename,
        $worksheet_index=$this.worksheet_index
    )`
    {
        $this.filename = $filename
        $this.worksheet_index = $worksheet_index

        $data_by_row = $this.from_excel_as_csv() # $data_by_row = $file.from_excel_as_csv($test_file)
        $data_by_row = $data_by_row -split"`n"
        #if ($this.headers.count -lt 1) {$this.headers = $data_by_row[0] -split $this.delimiter} #this would let us set headers elsewhere which is more flexible but less adaptive, Because columns change unpredicably we need something more adaptive
        $temp_headers = $data_by_row[0] -split $this.delimiter
        $temp_headers = $this.fix_blank_headers($temp_headers)
        $this.headers = $this.dedupe_headers($temp_headers)
        $this.data = $data_by_row|select -Skip 1|ConvertFrom-Csv -Header $this.headers -Delimiter $this.delimiter
    }
    function from_csv($filename=$this.filename)`
    {
        $this.filename = $filename
        $this.headers = (Get-Content $this.filename -ReadCount 1|select -first 1) -split $this.delimiter
        $this.data = Get-Content $this.filename|ConvertFrom-Csv -Delimiter $this.delimiter
    }
    function from_excel_as_csv(
        $filename=$this.filename,
        $worksheet_index=$this.worksheet_index
    )`
    {
        $this.filename = $filename
        $this.worksheet_index = $worksheet_index

        #set up excel
        Write-Host "Importing from excel, this may take a little while..."
        $excel = New-Object -ComObject Excel.Application
        $excel.DisplayAlerts = $false
        $excel.Visible = $false
        $workbook = $excel.workbooks.open($this.filename)
        $worksheet = $workbook.Worksheets.Item($this.worksheet_index)

        #import from excel
        try{
            $data_by_row = ""
            $indexed_column = $worksheet.columns.item($this.indexer_column).value2 #we use this to work around some files having headers with blank space
            $minimum_rows = (($indexed_column -join "◘").TrimEnd("◘") -split "◘").count # This Strips the million or so extra blank rows excel appends to get a realistic column length.
            [bool]$header_found = 0
            $i=1
            do `
            {
                $row = $worksheet.rows.item($i).value2
                $row_as_text = $row -join "◘" # ◘ (alt+8) is just a placeholder that's unlikely to show up in the text
                $row_as_text = $row_as_text -replace $this.delimiter,"."
                $row_as_text = $row_as_text.TrimEnd("◘")
                $row_as_text = $row_as_text -replace "◘",$this.delimiter
                if ($row_as_text -like "*$($this.header_contains)*"){[bool]$header_found=1}
                if ($header_found) {$data_by_row+="$row_as_text`n"}
                $i++
            }
            while ( ($row_as_text.Length -gt 1) -or ($i -lt $minimum_rows) )
        }
        catch {Write-Warning "ERROR Importing from excel"}

        #close excel
        $workbook.Close()
        $excel.Quit()
        write-host "Done importing from excel"
        return $data_by_row
    }
    function dedupe_headers($headers){
        $dupes = ($headers|group)|?{$_.count -gt 1}
        if ($dupes.count -ge 1)
        {
            foreach ($dupe in $dupes)
            {  #$dupe = $dupes[0]
                $i=1
                $new_headers = @()
                foreach ($header in $headers)
                {  #$header = $headers[0]
                    if ($header -eq $dupe.name)
                    {
                        $header = "$($header)_$($i)" # "header_#"
                        $i++
                    }
                    $new_headers += $header
                }
            }
        }
        else {$new_headers = $headers} # no duplicates found
        return $new_headers
    }
    function fix_blank_headers($headers)
    {
        $replace_blanks_with = "_"
        $new_headers = @()
        foreach ($header in $headers)
        {
            if ($header -eq "") {$new_headers += $replace_blanks_with}
            else {$new_headers += $header}
        }
        if ($new_headers.count -ne $header)
        {
            $error_json = @($headers),@($new_headers)|ConvertTo-Json -Compress
            Write-Error "Error when fixing blank headers, original and new counts are different $($error_json)"
        }
        return $new_headers
    }
    <# function some_function($some_parameter){return $some_parameter} #>
    Export-ModuleMember -Function * -Variable *
}
相关问题