#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, как вы предложили. Спасибо за помощь, это действительно прояснило ситуацию. Теперь я также вижу, что некоторые части моего кода были действительно устаревшими и / или ненужными.