2014-09-19 3 views
0

У меня есть некоторые данные в файле Excel с некоторыми горизонтальными и вертикальными размерами. Это выглядит следующим образом:Преобразование данных из Excel

enter image description here

Эти данные должны загружаться в какой-то BI системы. Для этого мне нужно преобразовать данные в «стиль таблицы». Другими словами, она должна быть представлена ​​в таблице, как это:

enter image description here

Мне нужен эффективный алгоритм, чтобы сделать это преобразование. Единственный, который, как мне известно, должен принимать значение от первой ячейки (100000), получает значения от вертикальных и горизонтальных координат (Россия, население, 1900 г.) и вставляет в первую строку. Затем возьмите еще одну ячейку и так далее.

Это будет работа с небольшим количеством данных, но с большим количеством он работает очень медленно. Знаете ли вы более сложный алгоритм для такого рода данных?

+0

Имеет ли порядок строк промежуточного выходного значения? Это что-то делать часто (вы не отметили [excel-vba])? – pnuts

+0

Сколько у вас данных? Если у вас было 100 стран, 100 индексов, более 100 лет, вы бы приблизились к ограничениям строки Excel для этого в одном наборе столбцов. –

+0

Если бы мне пришлось это сделать, я бы использовал 'python' с некоторыми модулями для чтения и записи файлов XLS. –

ответ

2

Существует несколько способов сделать это с помощью VBA. В этом решении я сначала создаю пользовательский Object с именем Country, с четырьмя свойствами: Name, Index, YR и Quantity. Это не нужно делать; но я недавно работал с ними, и я думаю, что он добавляет некоторую ясность в код.

Затем я считываю исходные данные в массив VBA (который может быть выполнен за один шаг), итерации по массиву для создания коллекции объектов Country.

Затем я просматриваю сборник Country, выводя свойства в массив Results, где я их хочу.

И наконец, массив результатов выводится на рабочий лист - снова, всего на один шаг.

Можно было перейти непосредственно из массива исходных данных в массив Results, но я думаю, что легче увидеть, что происходит с использованием объекта.

Также можно не беспокоиться с массивом VBA, но обрабатывать ячейки непосредственно с одного листа на другой. По моему опыту, этот подход будет по крайней мере на порядок медленнее, чем использование подхода массива VBA.

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

Чтобы определить объект Country, вставьте модуль класса и переименуйте его Страна. В этом модуле введите следующий код:

======================================================================================================================================================================== =====

Option Explicit 
Private pName As String 
Private pIndex As String 
Private pYr As Long 
Private pQuantity As Double 

Public Property Get Name() As String 
    Name = pName 
End Property 
Public Property Let Name(Value As String) 
    pName = Value 
End Property 

Public Property Get Index() As String 
    Index = pIndex 
End Property 
Public Property Let Index(Value As String) 
    pIndex = Value 
End Property 

Public Property Get Yr() As Long 
    Yr = pYr 
End Property 
Public Property Let Yr(Value As Long) 
    pYr = Value 
End Property 

Public Property Get Quantity() As Double 
    Quantity = pQuantity 
End Property 
Public Property Let Quantity(Value As Double) 
    pQuantity = Value 
End Property 

====================================== =======

Затем вставьте регулярный модуль и поместите этот код там:

======================= ================

Option Explicit 
Sub TransformData() 
    Dim wsSrc As Worksheet 'Data Source 
    Dim wsRes As Worksheet, rRes As Range 'Results go here 
    Dim vSrc As Variant 'Actual data goes into this array 
    Dim vRes() As Variant 'Results will go here before being written to worksheet 
    Dim cCTY As Country 'User defined object 
    Dim colCountries As Collection 
    Dim I As Long, J As Long 'counters 

Set wsSrc = Worksheets("Sheet2") '<--change these to whatever 
Set wsRes = Worksheets("Sheet3") 

Set rRes = wsRes.Range("A1") '<--1st cell of results array 

'read data into array 
With wsSrc 
    vSrc = .Range("A1").CurrentRegion '<--many ways to get this depending on your real data setup 
End With 

'iterate through Source and create collection of results 
Set colCountries = New Collection 
For I = 2 To UBound(vSrc, 1) '<--Rows 
    For J = 3 To UBound(vSrc, 2) '<--Columns 
     Set cCTY = New Country 
     With cCTY 
      .Name = vSrc(I, 1) 
      .Index = vSrc(I, 2) 
      .Yr = vSrc(1, J) 
      .Quantity = vSrc(I, J) 
     End With 
     colCountries.Add cCTY 
    Next J 
Next I 

'Results 
ReDim vRes(0 To colCountries.Count, 1 To 4) 

'Column Labels 
vRes(0, 1) = "Country" 
vRes(0, 2) = "Index" 
vRes(0, 3) = "Year" 
vRes(0, 4) = "Value" 

For I = 1 To colCountries.Count 
    With colCountries(I) 
     vRes(I, 1) = .Name 
     vRes(I, 2) = .Index 
     vRes(I, 3) = .Yr 
     vRes(I, 4) = .Quantity 
    End With 
Next I 

Set rRes = rRes.Resize(UBound(vRes, 1) + 1, UBound(vRes, 2)) 
rRes.EntireColumn.Clear 
rRes = vRes 
With rRes.Rows(1) 
    .Font.Bold = True 
    .HorizontalAlignment = xlCenter 
End With 
rRes.EntireColumn.AutoFit 

End Sub 

========================================================================================================================== ====

Убедитесь, что листы и диапазоны правильно определены в соответствии с вашей реальной настройкой и запустите макрос.