Загрузка CSV с нестандартным форматированием с использованием служб SSIS - PullRequest
0 голосов
/ 16 мая 2018

Мне поручено загрузить учетные транзакции, которые появляются в CSV-файле. Файл содержит одну строку информации заголовка, примененную ко всему файлу, но по какой-то причине он группирует данные по номеру счета над данными транзакции, но в том же столбце, что и идентификатор.

"ID","Name","Date","Debit","Credit","Balance"
,,,,,
"1150 - Cash in Bank",,,,,
"Starting Balance",,,,,"59,612.78"
615892,"Account Name 1","5/5/2018","2,100.00",,"61,712.78"
645761,"Account Name 2","5/7/2018",,7,"61,705.78"
615892,"Account Name 3","5/8/2018",,"2,144.33","59,561.45"
713300,"Account Name 4","5/8/2018","2,144.33",,"61,705.78"
713300,"Account Name 5","5/8/2018",,"2,144.33","59,561.45"
693615,"Account Name 6","5/9/2018",,"1,650.00","57,911.45"
"Net Change",,,,,"-1,701.33"
,,,"4,244.33","5,945.66","57,911.45"
"3150 - Owner Contribution",,,,,
"Starting Balance",,,,,0
713300,"Account Name 4","5/8/2018",,"2,144.33","-2,144.33"
"Net Change",,,,,"-2,144.33"
,,,0,"2,144.33","-2,144.33"

Может кто-нибудь подсказать мне, как я могу это обработать? Я вижу, как логически сделать это с помощью нескольких переменных и построчной обработки, но я вообще не являюсь разработчиком C # или front end. Моя самая большая проблема заключается в том, что вы не можете написать кусок и протестировать его, как SQL. Я могу запросить таблицу, посмотреть данные и продолжить ее построение, но с C # мне нужен целый скрипт для совместной работы. Как мне начать с небольшого блока и расширить? как даже чтение первого имени учетной записи в переменной и отображение его в виде переменной в задаче потока данных. Просто то, куда я могу отправить код и получить что-то обратно, похоже, что каждый скрипт, который я нахожу в сети, имеет некоторые ошибки компиляции, и я пока не знаю достаточно, чтобы их устранить.

Ответы [ 3 ]

0 голосов
/ 17 мая 2018

Обзор решения

Я представил свой ответ в VB.Net, потому что это может быть легче понять, особенно если вы не являетесь разработчиком C #

  • ВDataflow task добавить Script Component после Flat File Source
  • In пометить все столбцы как входной столбец и добавить 8 выходных столбцов
  • В Input0_ProcessInputRow проверить, если столбец ID не пусти оно содержит целое число для создания выходной строки, иначе, если оно содержит номер счета или начальное сальдо, сохраняют эти значения в переменных, иначе игнорирует строку.

Подробное решение

  1. Добавление диспетчера соединений с плоским файлом, выберите текстовый файл
  2. Измените квалификатор текста на "

enter image description here

Добавление задачи DataFlow Внутри задачи потока данных добавьте источник плоских файлов, компонент сценария и назначение OLEDB

enter image description here

В компоненте «Сценарий» выберите все столбцы в качестве входного столбца

Добавьте 8 выходных столбцов (основные столбцы + счет + начальный баланс) (все типа * 1049)*)

enter image description here

Измените свойство OutputBuffer SynchronousInput на None

enter image description here

Выберите язык сценариев для Visual Basic

enter image description here

В редакторе скриптов напишите следующий скрипт

Private AccountName as String = ""
Private StartingBalance as String = ""
    Public Overrides Sub Input0_ProcessInputRow(ByVal Row As Input0Buffer)

        If Not Row.ID_IsNull AndAlso
                Not String.IsNullOrEmpty(Row.ID.Trim) Then


            'Skip Bad Rows
            If Row.ID = "" Then Exit Sub

            If Integer.TryParse(Row.ID,New Integer) Then

                Output0Buffer.AddRow()
                Output0Buffer.ID = Row.ID
                Output0Buffer.Name = Row.Name
                Output0Buffer.Date = Row.Date
                Output0Buffer.Debit = Row.Debit
                Output0Buffer.Credit = Row.Credit
                Output0Buffer.Balance = Row.Balance
                Output0Buffer.Account = AccountName
                Output0Buffer.StartingBalance = StartingBalance

            Elseif Row.ID.Contains("Starting Balance") Then

                StartingBalance = Row.Balance

            Elseif Row.ID.Contains("-") Then

                AccountName = Row.ID

            Else 


                'Ignore Row 
                Exit Sub

            End If






        End If

    End Sub
Сопоставить столбцы вывода с столбцами назначения Вывод будет:

enter image description here

0 голосов
/ 26 мая 2018

Я только что наткнулся на этот пост. Пройдя очень похожий опыт всего 1 день назад, я бы порекомендовал запустить макрос ниже (его можно запустить в Excel или CSV, но вы не можете сохранить код, если сохраните изменения с расширением CSV).

' Add reference to Microsoft Active X Data Objects 2.8 Library                                                           

Sub testexportsql()
    Dim Cn As ADODB.Connection
    Dim ServerName As String
    Dim DatabaseName As String
    Dim TableName As String
    Dim UserID As String
    Dim Password As String
    Dim rs As ADODB.Recordset
    Dim RowCounter As Long

    Dim NoOfFields As Integer
    Dim StartRow As Long
    Dim EndRow As Long

    Dim ColCounter As Integer


    Set rs = New ADODB.Recordset


    ServerName = "server_name" ' Enter your server name here
    DatabaseName = "db_name" ' Enter your  database name here
    TableName = "table_name" ' Enter your Table name here
    UserID = "" ' Enter your user ID here
     ' (Leave ID and Password blank if using windows Authentification")
    Password = "" ' Enter your password here
    NoOfFields = 10 ' Enter number of fields to update (eg. columns in your worksheet)
    StartRow = 2 ' Enter row in sheet to start reading  records
    EndRow = 100 ' Enter row of last record in sheet

     '  CHANGES
    Dim shtSheetToWork As Worksheet
    Set shtSheetToWork = ActiveWorkbook.Worksheets("sheet_name")
     '********

    Set Cn = New ADODB.Connection
    Cn.Open "Driver={SQL Server};Server=" & ServerName & ";Database=" & DatabaseName & _
    ";Uid=" & UserID & ";Pwd=" & Password & ";"

    rs.Open TableName, Cn, adOpenKeyset, adLockOptimistic

     'EndRow = shtSheetToWork.Cells(Rows.Count, 1).End(xlUp).Row
    For RowCounter = StartRow To EndRow
        rs.AddNew
        For ColCounter = 1 To NoOfFields
            rs(ColCounter - 1) = shtSheetToWork.Cells(RowCounter, ColCounter)
        Next ColCounter
        Debug.Print RowCounter
    Next RowCounter
    rs.UpdateBatch

     ' Tidy up
    rs.Close
    Set rs = Nothing
    Cn.Close
    Set Cn = Nothing

End Sub

Надеюсь, это решение подойдет вам. Это определенно сработало для меня.

0 голосов
/ 16 мая 2018

Это должно привести все это в структуру DataTable, которую вы затем можете использовать, чтобы назначать или делать с чем угодно.Если вам нужен другой тип конечного объекта, дайте мне знать.

        var data = string.Empty; //String var to hold file
        var tbl = new DataTable("MyData"); //Tmp dataTable object
        using (var fs = new StreamReader(@"C:\Temp\test.csv")) //Open file
            data = fs.ReadToEnd(); //Read entirely into data variable

        var rows = data.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries); //Split into array by lines. RemoveEmpty's for end of file extra lines.

        var cnt = 0; //Counter to know header
        foreach (var row in rows) //Iterate rows
        {
            var cells = row.Split(new string[] { "\",\"" }, StringSplitOptions.None); //Split row into cells. Leave empties here cause some cells might be empty.
            if (cnt == 0) foreach (var cell in cells) //If is header row add columns
                    tbl.Columns.Add(new DataColumn(cell));
            else //Else data row
            {
                var dataRow = tbl.NewRow(); //New row
                dataRow.ItemArray = cells; //Assign cell values
                tbl.Rows.Add(dataRow); //Add row to table.
            }
            cnt++;
        }

РЕДАКТИРОВАТЬ: Очистить с помощью и добавить комментарии.

РЕДАКТИРОВАТЬ 2: Вот потоковая версия, если файлы слишком большие:

        var cnt = 0; //Row counter
        var tbl = new DataTable("MyData"); //Tmp dataTable object
        using (var fs = new StreamReader(@"C:\Temp\test.csv")) //Load file
        {
            do //Start loop
            {
                var row = fs.ReadLine(); //Get first line
                var cells = row.Split(new string[] { "\",\"" }, StringSplitOptions.None); //Split into cells
                if (cnt == 0) //If is header row
                {
                    foreach (var cell in cells) //For each header
                        tbl.Columns.Add(new DataColumn(cell)); //Add Column
                } else { //Not header row
                    var dataRow = tbl.NewRow(); //Create new row based on tmp table
                    dataRow.ItemArray = cells; //Assign cell values
                    tbl.Rows.Add(row); //Add row to table
                }
                cnt++;
            } while (!fs.EndOfStream); //If not done loop
        }
...