Set-ADUser跳过xlsx中的空单元格

时间:2018-10-15 14:52:44

标签: powershell active-directory

我想从.xlsx批量更新DC用户,但脚本应跳过xlsx数据中的空值。

我已经用几种方法尝试过,但是没有用。

第一次尝试是

hash.GetEnumerator() | foreach {
    if ($_.Value -eq "") {
        $hash.Remove($_.Key)
    }
}

Secound尝试如下代码所示:

foreach ($h in $hash.Keys) {
    if ($(hash.Item($h)) -eq "") {
        $hash.Remove($h)
try {
    Import-Module ActiveDirectory -ErrorAction Stop -WarningAction Stop
} catch {
    Write-Host "ActiveDirectory module not found!!" -ForegroundColor Red -BackgroundColor Black
    Write-Host "Script Aborted." -ForegroundColor Red -BackgroundColor Black
    # Abort the script.
    break
}

try {
    $credential = Get-Credential

    [Threading.Thread]::CurrentThread.CurrentCulture = 'en-US'
    #Declare file path and sheet name
    $file = "...\UpdateUsers_test.xlsx"
    #Create an Excel.Application instance and open that file
    $Excelobject = New-Object -ComObject Excel.Application
    $Workbook = $Excelobject.Workbooks.Open($file)
    $sheetName = "Sheet1"
    $sheet = $Workbook.Worksheets.Item($sheetName)
    #$objExcel.Visible=$true

    #Count max row
    $rowMax = ($sheet.UsedRange.Rows).Count
    #Count max column
    $colMax = ($sheet.UsedRange.Columns).Count
    $hash = @{}
    $server = "IP-Address"

    #Specify starting positions
    $row, $col = 1, 1
    $updatedCount = 0

    #loop for rows
    for ($i=1; $i -le $rowMax-1; $i++) {
        #loop for columns
        for ($c=0; $c -le $colMax-1; $c++) {
            #Get all columns values to a hash
            $hash += @{$sheet.Cells.Item($row, $col+$c).Text = $sheet.Cells.Item($row+$i, $col+$c).Text}

            foreach ($h in $hash.Keys) {
                if ($(hash.Item($h)) -eq "") {
                    $hash.Remove($h)
                }

                #Create an object and assign hash keys as object property
                $Object = New-Object -TypeName PSObject -Property $hash

                #Get User via SamAccountname
                $user = Get-ADUser -Filter "SamAccountName -eq '$($Object.UserName)'" -
SearchBase 'DC=Domain, DC=local' -Server $server -Credential $credential

                #Set Users attribute with matched object attribute
                $user | Set-ADUser -DisplayName $Object.Displayname `
                    -OfficePhone $Object.PhoneNumber `
                    -EmailAddress $Object.email `
                    -Postalcode $Object.Postalcode `
                    -City $Object.City `
                    -Streetaddress $Object.Streetaddress `
                    -Country $Object.Country `
                    -Office $Object.Office `
                    -Title $Object.Title `
                    -Company $Object.Company `
                    -Department $Object.Department `
                    -Manager $Object.Manager `
                    -Mobile $Object.Mobile `
                    -Fax $Object.Fax

                #If you want to edit Object common name, you can remove enable two lines
below.

                #$userguid = $user.ObjectGUID.Guid
                #$user | Rename-ADObject -NewName $Object.DisplayName -Server $server -
Credential $credential

                $hash = @{}
                Write-Host $User.Name "- User attributes have been updated." -
ForegroundColor Yellow
                Start-Sleep -s 1
                $updatedCount += 1
            }

            Write-Host $updatedCount "Users have been updated" -ForegroundColor Green

            #close excel file
            $Excelobject.Quit()
        }

catch {
    Write-Error $_.Exception.ToString()
    Read-Host -Prompt "The above error occured. Press Enter to exit."
}

3 个答案:

答案 0 :(得分:0)

我认为更好的方法是通过PSObject。有时一条记录可以具有多个属性,使用''搜索空值可能会很困难。

相反,您可以使用PSObject属性并搜索空值:

$_.PSObject.Properties | ForEach-Object {$_.Value}) -eq $null

答案 1 :(得分:0)

我想我建议您使用splatting而不是创建对象,这将涉及使用哈希表为Set-ADUser指定参数。若要进行此工作,哈希表的键必须与cmdlet的参数相同。您的关系密切,但是有一些差异,因此首先我们需要创建一个哈希表,以将您的电子表格映射到正确的参数。将其放在循环行之前。

$ParamMap = @{
    Displayname = 'DisplayName' 
    PhoneNumber = 'OfficePhone' 
    email = 'EmailAddress' 
    Postalcode = 'Postalcode' 
    City = 'City' 
    Streetaddress = 'Streetaddress' 
    Country = 'Country' 
    Office = 'Office' 
    Title = 'Title' 
    Company = 'Company' 
    Department = 'Department' 
    Manager = 'Manager' 
    Mobile = 'Mobile' 
    Fax = 'Fax'
}

现在,我们稍微修改一下如何创建哈希表以使用它来查找键名(这将替换您的$hast +=行):

                $hash.add($ParamMap[$sheet.Cells.Item($row, $col+$c).Text], $sheet.Cells.Item($row+$i, $col+$c).Text)

现在我们有了哈希表,我们可以检查null或空字符串,并将其删除。

                $hash.keys | Where{ [string]::IsNullOrWhitespace($hash[$_]) } | ForEach-Object { $Hash.Remove($_) }

该行枚举$hash的键,并检查每个键的值以查看其是否包含空值或仅包含空格(空格,制表符,换行)。如果它为null或空格,则会从哈希表中删除该键。

现在,我们有了一个哈希表,该哈希表仅具有表示cmdlet参数的有效键,并且每个键都有一个值,我们将其喷溅到Get-ADUser cmdlet中,我们就完成了设置。

                $user | Set-ADUser @hash

答案 2 :(得分:0)

@TheMadTechnician
谢谢!
您的回答对我很有帮助。但是我仍然存在将哈希表传递给Set-ADUser cmdlet的问题。
不幸的是,我自己无法解决这些错误消息

#loop for rows 
for ($i=1; $i -le $rowMax-1; $i++)
{

    #loop for columns
    for($c=0; $c -le $colMax-1; $c++)
    {
      #Get all columns values to a hash

      $hash += @{$sheet.Cells.Item($row, $col+$c).Text = $sheet.Cells.Item($row+$i, $col+$c).Text}

      $hash.keys.Clone() | Where{ [string]::IsNullOrWhitespace($hash[$_]) } | ForEach-Object { $Hash.Remove($_) }
      $hash | Out-String | Write-Host

    }


   #Create an object and assign hash keys as object property
   $Object = New-Object -TypeName PSObject -Property $hash

   #Get User via SamAccountname  
   $user = Get-ADUser -Filter "SamAccountName -eq '$($Object.SamAccountName)'" -SearchBase 'DC=domain, DC=local' -Server $server -Credential $credential 


}

   #Set Users attribute with matched object attribute
   $user | Set-ADUser   -Replace EmailAddress = $Object.Email; `
                        -Postalcode $Object.Postalcode `
                        -City $Object.City `
                        -Streetaddress $Object.Streetaddress `
                        -Country $Object.Country `
                        -Office $Object.Office `
                        -Title $Object.Title `
                        -Company $Object.Company `
                        -Department $Object.Department `
                        -Manager $Object.Manager `
                        -Mobile $Object.Mobile `
                        -Fax $Object.Fax 
  

System.Management.Automation.ParameterBindingException:无法绑定参数“替换”。无法转换   类型为“ System.String”的“ EmailAddress”值将类型为“ System.Collections.Hashtable”。 ->   System.Management.Automation.PSInvalidCastException:无法转换类型为“ System.String”的“ EmailAddress”值   键入“ System.Collections.Hashtable”。      在System.Management.Automation.LanguagePrimitives.ThrowInvalidCastException(对象valueToConvert,类型resultType)      在System.Management.Automation.LanguagePrimitives.ConvertNoConversion(Object valueToConvert,类型resultType,   布尔递归,PSObject originalValueToConvert,IFormatProvider formatProvider,TypeTable backupTable)      在System.Management.Automation.LanguagePrimitives.ConversionData 1.Invoke(Object valueToConvert, Type resultType, Boolean recurse, PSObject originalValueToConvert, IFormatProvider formatProvider, TypeTable backupTable) at System.Management.Automation.LanguagePrimitives.ConvertTo(Object valueToConvert, Type resultType, Boolean recursion, IFormatProvider formatProvider, TypeTable backupTypeTable) at System.Management.Automation.ParameterBinderBase.CoerceTypeAsNeeded(CommandParameterInternal argument, String parameterName, Type toType, ParameterCollectionTypeInformation collectionTypeInfo, Object currentValue) --- End of inner exception stack trace --- at System.Management.Automation.ExceptionHandlingOps.CheckActionPreference(FunctionContext funcContext, Exception exception) at System.Management.Automation.Interpreter.ActionCallInstruction 2.Run(InterpretedFrame框架)处      在System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame框架)      在System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame框架)