Excel, CSV ja Powershell

Aeg-ajalt on meil vaja tegeleda CSV failidega.  See lühend peaks tähendama Comma Separated Value ent Excelil on sellest oma arusaam.  Nimelt kasutab Excel regiooni seadetest loendieraldajat, ning Eesti seadete korral on selleks koma asemel semikoolon.  Ja kui Excelis teha valmis kasutajate nimikiri, kellele oleks vaja teha kasutajakonto ja postkast, siis on CSV-failiks salvestamise tulemus järgmine

Eesnimi;Perenimi;osakond
Mati;Mõisnik;Müük
Kätlin;Pöögelman;Arendus

Ja kui seda faili püüda Powershellis importida, siis tekib kaks probleemi:

  1. Import-CSV eeldab, et CSV fail on salvestatud ASCII kodeeringus (ehk siis täpitähed on paigast ära)
  2. semikoolon on Import-CSV jaoks vale eraldaja

Esimese probleemi vastu on lihtne lahendus: Get-Content oskab faili sisu õiges kodeeringus kätte saada.  Ainult et Get-Content annab meile faili tekstistringidena.  Õnneks on meil olemas käsk ConvertFrom-CSV:

#Requires -Version 3

Get-Content .\Vihik1.csv | ConvertFrom-Csv -UseCulture

Käsurea parameeter UseCulture hoolitseb selle eest, et kasutataks õiget loendieraldajat.

Sarnane probleem tekib meil ka siis, kui oleks vaja näiteks kasutajakonto info eksportida Excelisse:

#Requires -Version 3

Get-ADUser -Filter  {(Enabled -eq $true) -and (City -like "Tallinn")} `
    -Properties mail |
  Select-Object *name, mail |
  ConvertTo-Csv -UseCulture -NoTypeInformation|
  Out-File kasutajad.csv

Aga ehk saaks ka Import-CSV ja Export-CSV õigesti tööle?  Tegelikult saabki:

#Requires -Version 3
import-csv .\Vihik1.csv -Encoding Default -UseCulture

Get-ADUser -Filter  {(Enabled -eq $true) -and (City -like "Tallinn")} `
    -Properties mail |
  Select-Object *name, mail |
  Export-Csv kasutajad.csv -Encoding Default -UseCulture

Häda on vaid selles, et kui nüüd sama skript viia mõnda teise riiki, siis tuleks kasutada teist loendieraldajat.  Õnneks on loendieraldajat võimalik süsteemi käest küsida:

Get-Culture
(Get-Culture).TextInfo
(Get-Culture).TextInfo.ListSeparator

(Get-Culture).GetType().FullName
  # Powershell ISE korral
(Get-Culture).GetType().BaseType.FullName

Tuleb vaid meeles pidada, et loendieraldaja on kasutajapõhine seadistus ja kui CSV fail läheb teise inimese kätte või tuleb teise inimese käest, siis tuleb teada tema keele-eelistusi:

$kultuur = [System.Globalization.CultureInfo]"en-us"
$eraldaja = $kultuur.TextInfo.ListSeparator
Import-Csv .\Vihik1.csv -Encoding Default -Delimiter $eraldaja
Advertisements