Создание электронной таблицы Excel из нескольких файлов CSV - PullRequest
0 голосов
/ 29 ноября 2018

У меня есть 1 книга Excel с одним листом и 3 файла CSV.Рабочий лист имеет фиксированное количество столбцов (с заголовками) и различное количество строк.Один столбец содержит поле «ID», а три последних столбца не заполнены.Каждый CSV имеет различное количество столбцов, но у всех есть поле «ID», которое должно соответствовать полю «ID» на листе Excel.Хотя в листе Excel может быть несколько экземпляров одного и того же идентификатора, в CSV нет повторяющихся идентификаторов.Например:

Файл Excel

ID:     Name:   Color:  Location:   Age:    Siblings:
123     Bob     Red
234     Sally   Green
345     Donald  Orange
123     Bob     Black

CSV1

ID:     Name:   Place:  Animal: Location:   Car:
123     Bob     Here    Dog     Up          Ferarri
234     Sally   There   Cat     Down        Porsche
345     Donald  Nowhere Squid   Right       Yugo

CSV2

ID:     Name:   Place:  Age:    
123     Bob     Here    50      
234     Sally   There   45      
345     Donald  Nowhere 100

CSV3

ID:     Siblings:
123     Five
234     Three
345     Eight

Цель состоит в том, чтобы добавить данные из определенных столбцов в файлах CSV в файл Excel на основе соответствующих идентификаторов.Ожидаемый результат будет следующий файл Excel:

ID:     Name:   Color:  Location:   Age:    Siblings:
123     Bob     Red     Up          50      Five
234     Sally   Green   Down        45      Three
345     Donald  Orange  Right       100     Eight
123     Bob     Black   Up          50      Five

Я потратил довольно много времени, пытаясь найти наиболее эффективный (быстрый) метод для этого и думаю, что я столкнулся с кирпичной стеной.Что у меня есть (в соответствующей части):

# Pull relevant data from csv files together #
$rtFile = $selectedDirectory + "\\" + "*RT*.csv"
$seFile = $selectedDirectory + "\\" + "*SE*.csv"
$lmFile = $selectedDirectory + "\\" + "*LM*.csv"

$rtCSV = Import-Csv $rtFile | select ID, LOCATION
$seCSV = Import-Csv $seFile | select ID, AGE
$lmCSV = Import-Csv $lmFile | select ID, SIBLINGS

$rtCSV | ForEach {$_ | Add-Member 'AGE' $null}
$rtCSV | ForEach {$_ | Add-Member 'SIBLINGS' $null}

foreach ($record in $rtCSV) {
    $record.'AGE' = $seCSV | Where {$_.ID -eq $record.ID} | Select -Expand 'AGE'
    $Record.'SIBLINGS' = $lmCSV | Where {$_.ID -eq $record.ID} | Select -Expand 'SIBLINGS'
}

# Add Data to Excel Sheet #
$WorkSheet.Activate()
$range = $WorkSheet.Range("C1").EntireColumn

foreach ($searchStr in $rtCSV.ID) {
    $search = $range.Find($searchStr)

    if ($search -ne $null) {
        $firstAdr = $search.Address(0, 0, 1, 0)

        do {
            $WorkSheet.Cells.Item($search.row,17).Value() = $rtCSV[$search.row].LOCATION
            $WorkSheet.Cells.Item($search.row,18).Value() = $rtCSV[$search.row].AGE
            $WorkSheet.Cells.Item($search.row,19).Value() = $rtCSV[$search.row].SIBLINGS

            $search = $range.FindNext($search)
        } while ($search -ne $null -and $search.Address(0, 0, 1, 0) -ne $firstAdr)
    }
}

Это заняло у меня некоторое время, но я наконец понял, почему вышеприведенное не работает.Хотя $search.row возвращает соответствующую строку в документе Excel (и, следовательно, ее можно использовать для определения, в какую ячейку вставлять данные), она не возвращает соответствующий индекс (?) Для соответствующих значений в $rtCSV.Итак, как мне убедиться, что я вставляю правильные значения для LOCATION, AGE и SIBLINGS каждый раз, когда совпадают идентификаторы?

Если это невозможно в рамках текущей конструкции, есть ли другое (возможно, лучшее и более эффективное)путь?Вообще говоря, файл Excel не должен содержать более 1000 строк.

Ответы [ 2 ]

0 голосов
/ 01 декабря 2018

Если вашей главной заботой является производительность, рассмотрите две вещи:

Преобразование «таблиц поиска» (csv1, csv2, csv3) в хеш-таблицы, поэтому поиск будет быстрым (это несколько похоже на индексацию в базах данных)

Храните все данные в виде простых файлов (csv), чтобы избежать зависимостей и сделать ваш сценарий простым и эффективным.Затем вы можете связать свои данные с электронной таблицей в качестве представления, чтобы при необходимости применить форматирование (вы можете создать связанную таблицу и представления из CSV-файла в MS Access, а затем передать их в таблицу данных в Excel)

Нижеэто пример (для простоты используем некоторые другие псевдо-файлы).Вы также можете использовать объект листа в основном цикле (просто переходить по индексам строк и обновлять объекты ячеек).

# generate hashtables
$person = @{}
$location = @{}
Import-Csv location.csv | foreach {$location.Add($_.id, @{zip=$_.zip; city=$_.city})}
Import-Csv person.csv | foreach {$person.Add($_.id, @{name=$_.name; age=$_.age})}

# loop through the main file
Import-Csv main.csv | foreach {
    $id = $_.id
    $_.name = $person[$id].name
    $_.age = $person[$id].age
    $_.city = $location[$id].city
    $_.zip = $location[$id].zip
    Write-Output $_ } | Convertto-Csv | Out-File mainOut.csv
0 голосов
/ 29 ноября 2018

Если вы не возражаете против установки дополнительных модулей, чтобы упростить вашу работу, я настоятельно рекомендую dfinke's Import Excel module .Как только вы установите if, код для достижения вашей цели будет прост:

# cd C:\SO\53529676
$rtCSV = Import-Csv .\csv1.csv | select ID, LOCATION
$seCSV = Import-Csv .\csv2.csv | select ID, AGE
$lmCSV = Import-Csv .\csv3.csv | select ID, SIBLINGS
$excel = Import-Excel .\Excel1.xlsx

foreach ($record in $excel) {
  $record.'LOCATION' = ($rtCSV | Where {$_.ID -eq $record.ID}).LOCATION
  $record.'AGE' = ($seCSV | Where {$_.ID -eq $record.ID}).AGE
  $Record.'SIBLINGS' = ($lmCSV | Where {$_.ID -eq $record.ID}).SIBLINGS
}

$excel | Export-Excel .\Excel2.xlsx
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...