PowerShell Compare-объект и экспорт-экспорт неправильных данных в Csv

#powershell #csv #compareobject

#powershell #csv #compareobject

Вопрос:

Проблема

У меня есть два файла CSV, файл A и файл B. Оба файла содержат один и тот же заголовок.
Файлы содержат информацию о котировках и заказах.

Файл A был создан первым, скажем, в 10:00 утра. Файл B был создан в 11:00 утра. Именно тогда значение столбца состояния обновляется с ‘Quote’ на ‘Order’ и, возможно, некоторые другие детали.

Я использую Compare-Object и Export-Csv объединяю для экспорта различий в новый файл CSV, но следует экспортировать только самую свежую (актуальную) информацию.
Проблема Compare-Object в том, что правильно определяет, что определенная строка была изменена, но вместо использования данных из файла B используются данные из файла A (более старая версия).

Пример (содержимое файла)

Я выделил поля, которые изменились, жирным шрифтом.

Файл A

"CustomerName","Address","Postalcode","City","ReferenceNumber","CustomerNumber","Statuscode","DeliveryWeek","WorkDescription","Status","OrderReference","Advisor" 
"Пример клиента", "Пример адреса 1", "9999 EX", "ПРИМЕР ГОРОДА","217098","8629",**" Цитата"**,**""**," Пример продукта", "Статус примера", "Частный", "ПримерСоветник"

Файл B

"CustomerName","Address","Postalcode","City","ReferenceNumber","CustomerNumber","Statuscode","DeliveryWeek","WorkDescription","Status","OrderReference","Advisor" 
"Пример клиента", "Пример адреса 1", "9999 EX", "ПРИМЕР ГОРОДА","217098","8629",**" Заказ"**,** "Отмена заказа"**, "Пример товара", "Пример статуса", "Частный", "Пример советника"

Сценарий

Хорошо, там довольно много строк. Я поделюсь строками, в которых, по моему мнению, должна находиться проблема.

 $timestamp = (get-date -UFormat "%A %d-%m-%Y %R" | ForEach-Object { $_ -replace ":", "-" })
$prefix="Export-"
$exportlocation = "C:UsersusernameDesktopUTF8-format" 
$ExportChangesFolder = "C:UsersusernameDesktopChanges"

$PreviousCSV = Import-Csv $PreviousFile -Header "CustomerName","Address","Postalcode","City","ReferenceNumber","CustomerNumber","Statuscode","DeliveryWeek","WorkDescription","Status","OrderReference","Advisor"
$NewCSV = Import-Csv $exportlocation$prefix$timestamp".csv" -Header "CustomerName","Address","Postalcode","City","ReferenceNumber","CustomerNumber","Statuscode","DeliveryWeek","WorkDescription","Status","OrderReference","Advisor"

$propsToCompare = $PreviousCSV[0].psobject.properties.name
Compare-Object -ReferenceObject $PreviousCSV -DifferenceObject $NewCSV -Property $propsToCompare -PassThru | select $propsToCompare | sort -Unique -Property "ReferenceNumber" | Select-Object * -ExcludeProperty SideIndicator | Export-Csv $ExportChangesFolder$prefix$timestamp".csv" -NoTypeInformation 
 

Обычно все имена файлов заполняются автоматически, поскольку это повторяющаяся настройка задачи с помощью планировщика задач Windows. Во время устранения неполадок я вручную ввел имена файлов, в которых объявлены переменные. И каждый раз, когда я запускаю его вручную, он работает нормально!

Ответ №1:

Я думаю, что вам может не хватать SideIndicator . Вы должны иметь возможность просто выбрать SideIndicators нужный вам список, в котором «» <= — это то, что существует только в левом csv, а « => » — это то, что существует только в правом.

Похоже, вы также указываете заголовки, а затем извлекаете заголовки из csv, но вы упомянули, что у них одинаковые заголовки?

Во Get-Date время выполнения таргетинг на существующий файл Import-Csv также немного сбивает с толку, но я предполагаю, что в скрипте есть нечто большее, что создает этот csv перед его импортом и Get-Date запуском.

Вот что-то, что работает с моей стороны:

 $timestamp = ((get-date -UFormat "%A %d-%m-%Y %R") -replace ":", "-")
$prefix="Export-"
$exportLocation = "C:UsersusernameDesktopUTF8-format" 
$exportChangesFolder = "C:UsersusernameDesktopChanges"

$headers = $previousCSV[0].psobject.properties.name

$previousCSV = Import-Csv $previousFile
$newCSV = Import-Csv $exportLocation$prefix$timestamp".csv"

$compareParams = @{
    ReferenceObject  = $previousCSV
    DifferenceObject = $newCSV
    Property         = $headers
    PassThru         = $true
}

Compare-Object @compareParams |
    Where-Object {$_.SideIndicator -eq "=>"} |
    Select-Object $headers | 
    Sort-Object -Unique -Property "ReferenceNumber" | 
    Select-Object * -ExcludeProperty SideIndicator |
    Export-Csv $exportChangesFolder$prefix$timestamp".csv" -NoTypeInformation
 

Комментарии:

1. Привет, Эндрю, спасибо! Я более подробно рассмотрел, как использовать SideIndicator, кажется, что когда я включаю {$_ . SideIndicator -eq «=>»}, он будет передавать информацию только тогда, когда номер ссылки существует только в файле B. В моем случае номер ссылки будет присутствовать в обоих файлах, но значение статуса будет обновлено в B. Правильно ли я это делаю, используя {$_ . SideIndicator -eq «=>»} не приведет к желаемому результату? «… значение свойства появилось только в ссылочном объекте (<=) или только в разностном объекте (=>). Если используется параметр IncludeEqual, (==) указывает, что значение находится в обоих объектах. »

2. Думаю, на этот раз я все понял правильно! Я совсем новичок в этом материале для сравнения объектов. Поскольку мы включаем Select-Object *, он обрабатывает все свойства как единое целое (объект), верно? Очевидно, что недостающим элементом головоломки был SideIndicator, как вы предложили. Спасибо за помощь, это действительно прояснило ситуацию. Теперь я также вижу, что некоторые части моего кода были действительно устаревшими и / или ненужными.