我有一些数据在Excel文件中有一些水平和垂直的尺寸。它看起来像这样:从Excel数据转换
这个数据必须被加载到一些BI系统。为此,我必须将数据转换为“表格样式”。换句话说,它应该在表中给出这样的:
我需要一些有效的算法,使这一转变。我知道的唯一一个就是从第一个单元格(100000)获取值,并从垂直和水平坐标(俄罗斯,人口,1900)中获取数值并插入第一行。然后再取另一个单元格等。
这将是少量的数据工作,但大量它的工作非常缓慢。你知道这种数据更复杂的算法吗?
我有一些数据在Excel文件中有一些水平和垂直的尺寸。它看起来像这样:从Excel数据转换
这个数据必须被加载到一些BI系统。为此,我必须将数据转换为“表格样式”。换句话说,它应该在表中给出这样的:
我需要一些有效的算法,使这一转变。我知道的唯一一个就是从第一个单元格(100000)获取值,并从垂直和水平坐标(俄罗斯,人口,1900)中获取数值并插入第一行。然后再取另一个单元格等。
这将是少量的数据工作,但大量它的工作非常缓慢。你知道这种数据更复杂的算法吗?
用VBA做这件事有几种方法。在这个解决方案中,我首先创建一个名为Country的用户定义Object,其中包含四个属性:Name,Index,YR和Quantity。没有必要这样做;但我最近一直在与这些工作,我认为它增加了代码的一些清晰度。
然后,我将源数据读入VBA数组(可以在一个步骤中完成),迭代数组以创建Country对象的集合。
然后我通过国家集合,将属性输出到结果数组中,我想要它们。
最后,结果数组输出到工作表 - 再次,只是一个步骤。
可以直接从Source数据数组转到Results数组,但我认为使用该对象更容易看到会发生什么。
人们也可能不打扰VBA阵列,但直接从一个工作表处理单元格到另一个。根据我的经验,这种方法至少比使用VBA阵列方法慢一个数量级。
根据数据库的大小,可能需要改进。一定要阅读代码中的评论。
要定义Country对象,请插入一个Class Module并将其重命名为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
================================================ ====
确保正确定义工作表和范围以符合您的真实设置并运行宏。
临时输出的行顺序是否重要?这是经常做的事情吗(你没有用[excel-vba]标记)? – pnuts 2014-09-19 20:11:43
你有多少数据?如果你有100个国家,100多个指数,超过100年,你会接近Excel排行限制,在一组列中完成此操作。 – 2014-09-19 21:49:46
如果我必须这样做,我会在一些模块中使用'python'来读写XLS文件。 – 2014-09-20 00:59:23