我在Excel文件中有一些数据,包含一些水平和垂直尺寸。它看起来像这样:
此数据必须加载到某个BI系统中。为此,我必须将数据转换为“表格样式”。换句话说,它应该如下表所示:
我需要一些有效的算法来进行这种转换。我知道的唯一一个是从第一个单元格(100000)获取值从垂直和水平坐标(俄罗斯,人口,1900)获取值并插入第一行。然后拿另一个细胞等等。
它可以处理少量数据,但是数量很大,它的工作速度非常慢。你知道更复杂的算法吗?
答案 0 :(得分:2)
使用VBA有几种方法可以做到这一点。在此解决方案中,我首先创建一个名为Country的用户定义对象,其中包含四个属性:Name,Index,YR和Quantity。没有必要这样做;但我最近一直在研究它们,我认为它为代码增加了一些清晰度。
然后我将源数据读入VBA数组(可以在一个步骤中完成),遍历数组以创建Country对象的集合。
然后我浏览Country集合,将属性输出到Results数组中,我想要它们。
最后,结果数组输出到工作表 - 再次,只需一步。
可以直接从Source数据数组转到Results数组,但我认为使用该对象更容易看到发生了什么。
人们也可以不打扰VBA数组,但是将单元格直接从一个工作表处理到另一个工作表。根据我的经验,这种方法至少比使用VBA阵列方法慢一个数量级。
根据数据库的大小,可能需要进行改进。请务必阅读代码中的注释。
要定义国家/地区对象,请插入类模块并将其重命名为国家/地区。 将以下代码放在该模块中:
==========================================
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
=============================================== =====
确保正确定义工作表和范围以符合您的实际设置,然后运行宏。