Скрипт Powershell для разбиения списка на несколько массивов - PullRequest
0 голосов
/ 20 декабря 2018

Я очень новичок в PowerShell. У меня есть код, который мне помог сотрудник.Он работает на небольшом наборе данных.Однако я отправляю это на запрос бизнес-объектов SAP, и он будет принимать только около 2000 фрагментов данных.Каждый месяц объем данных, которые я должен запускать, будет варьироваться, но обычно он составляет около 7000-8000 пунктов.Мне нужна помощь, чтобы обновить мой скрипт, чтобы запустить список данных, создать массив, добавить в него 2000 элементов, а затем создать новый массив со следующими 2000 элементами и т. Д., Пока он не достигнет конца списка.

$source = "{0}\{1}" -f $ENV:UserProfile, "Documents\Test\DataSD.xls"

$WorkbookSource = $Excel.Workbooks.Open("$source")
$WorkSheetSource = $WorkbookSource.WorkSheets.Item(1)
$WorkSheetSource.Activate()
$row = [int]2
$docArray = @()
$docArray.Clear() |Out-Null

    Do
    {
        $worksheetSource.cells.item($row, 1).select() | Out-Null
        $docArray += @($worksheetSource.cells.item($row, 1).value())

        $row++
    }
    While ($worksheetSource.cells.item($row,1).value() -ne $null)

Так что для этого примера мне понадобится скрипт для создания 4 отдельных массивов.В первых 3 будет 2000 предметов, а в последнем 1200 предметов.

Ответы [ 3 ]

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

Это не 100%, но я настрою его чуть позже сегодня:

$docarray = @{}
$values = @()

$i = 0
$y = 0

for ($x = 0; $x -le 100; $x++) {
    if ($i -eq 20) {
        $docarray.add($y, $values)
        $y++
        $i=0
        $values = @()
    }

    $values += $x
    $i++
}
$docarray.add($y, $values) ## required

$docarray | Format-List

Если предел равен 2000, тогда вы должны установить вызов if на 2000.быть хеш-таблицей с количеством x:

Name  : 4
Value : {80, 81, 82, 83...}

Name  : 3
Value : {60, 61, 62, 63...}

Name  : 2
Value : {40, 41, 42, 43...}

Name  : 1
Value : {20, 21, 22, 23...}

Name  : 0
Value : {0, 1, 2, 3...}

При этом каждое имя в массиве хэшей имеет x значений, представленных итератором $ i в операторе if.

Вам следуетзатем сможете отправить его в свой запрос бизнес-объектов SAP с помощью цикла foreach со значениями для каждого элемента в хэш-массиве:

foreach ($item in $docarray) {
    $item.Values
}
0 голосов
/ 20 декабря 2018

Для этого есть несколько вариантов.Вы можете прочитать все из файла Excel в одном большом массиве и затем разбить его на более мелкие куски или добавить значения файла Excel в отдельные массивы во время чтения.
Код ниже делает именно это.

В любом случае, вам решать, когда вы действительно хотите отправить данные.

  1. немедленно обрабатывает каждый массив (отправляет его в запрос бизнес-объектов SAP) при чтении из Excel
  2. добавляет его в Hashtable, чтобы вы хранили все массивы вместе в памяти
  3. сохранить его на диске для последующего использования

В приведенном ниже коде я выбираю второй вариант для чтения данных в нескольких массивах и сохранения их в памяти в хеш-таблице.
Преимущество состоит в том, что вам не нужно прерывать чтение данных Excel, как с опцией 1. , и нет необходимости создавать и перечитывать промежуточные файлы, как с опцией 3.

$source = Join-Path -Path $ENV:UserProfile -ChildPath "Documents\Test\DataSD.xls"
$maxArraySize = 2000

$Excel = New-Object -ComObject Excel.Application
# It would speed up things considerably if you set $Excel.Visible = $false
$WorkBook = $Excel.Workbooks.Open($source)
$WorkSheet = $WorkBook.WorkSheets.Item(1)
$WorkSheet.Activate()

# Create a Hashtable object to store each array under its own key
# I don't know if you need to keep the order of things later, 
# but it maybe best to use an '[ordered]' hash here.
# If you are using PowerShell version below 3.0. you need to create it using
# $hash = New-Object System.Collections.Specialized.OrderedDictionary
$hash = [ordered]@{}

# Create an ArrayList for better performance
$list = New-Object System.Collections.ArrayList
# Initiate a counter to use as Key in the Hashtable
$arrayCount = 0
# and maybe a counter for the total number of items to process?
$totalCount = 0

# Start reading the Excel data. Begin at row $row
$row = 2
do {
    $list.Clear()
    # Add the values of column 1 to the arraylist, but keep track of the maximum size
    while ($WorkSheet.Cells.Item($row, 1).Value() -ne $null -and $list.Count -lt $maxArraySize) {
        [void]$list.Add($WorkSheet.Cells.Item($row, 1).Value())
        $row++
    }
    if ($list.Count) {
        # Store this array in the Hashtable using the $arrayCount as Key. 
        $hash.Add($arrayCount.ToString(), $list.ToArray())
        # Increment the $arrayCount variable for the next iteration
        $arrayCount++
        # Update the total items counter
        $totalCount += $list.Count
    }
} while ($list.Count)

# You're done reading Excel data, so close it and release Com objects from memory
$Excel.Close()
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($WorkSheet) | Out-Null
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($WorkBook) | Out-Null
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($Excel) | Out-Null
[System.GC]::Collect()
[System.GC]::WaitForPendingFinalizers()

# At this point you should have all arrays stored in the hash to process
Write-Host "Processing $($hash.Count) arrays with a total of $totalCount items"

foreach ($key in $hash.Keys) {
    # Send each array to a SAP business objects query separately
    # The array itself is at $hash.$key or use $hash[$key]
}
0 голосов
/ 20 декабря 2018

, чтобы это работало, вам нужно будет экспортировать данные в CSV или иным образом извлечь их в коллекцию, которая содержит все элементы.использование чего-то вроде StreamReader, вероятно, позволило бы ускорить обработку, но я никогда не работал с этим.[ blush ]

как только генерируется $CurBatch, вы можете передать это в любой процесс, который захотите.

$InboundCollection = 1..100
$ProcessLimit = 22
# the "- 1" is to correct for "starts at zero"
$ProcessLimit = $ProcessLimit - 1

$BatchCount = [math]::Floor($InboundCollection.Count / $ProcessLimit)

#$End = 0
foreach ($BC_Item in 0..$BatchCount)
    {
    if ($BC_Item -eq 0)
        {
        $Start = 0
        }
        else
        {
        $Start = $End + 1
        }

    $End = $Start + $ProcessLimit
    # powershell will happily slice past the end of an array
    $CurBatch = $InboundCollection[$Start..$End]

    ''
    $Start
    $End
    # the 1st item is not the _number in $Start_
    #    it's the number in the array @ "[$Start]"
    "$CurBatch"

    }

вывод ...

0
21
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22

22
43
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44

44
65
45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66

66
87
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88

88
109
89 90 91 92 93 94 95 96 97 98 99 100
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...