我正在使用Excel VBA并使用OleDB连接到PGSQL。不幸的是,oledb不允许引用聚合函数之外的列,其中group by已应用于表,因此我必须连接数据,但是我无法将数据(latestBMI)拆分为3个单独的列( eventdate | weight | bmi),因为权重和bmi值的长度不同,但除以管道分隔符。
这是表格通过提取的样子:
master_id : latestBMI
251 : 2008-05-08|84|26.8
2848 : 1992-11-23|86.71|27.3
2026 : 2002-04-16|105|31.6
22316 : 2014-02-28|107.955|35.1
16633 : 2005-07-04|70|25
9545 : 1997-04-08|82.73|24.9
我一直在尝试各种方法尝试SUBSTRING,CHARINDEX,LEN,LEFT | RIGHT,但失败了。 这是我目前的代码,但重量和bmi的SUBSTRING元素是我的问题:
Const sqlconnection = "Provider=oledb;" Dim conn As New Connection conn.ConnectionString = sqlconnection conn.Open Dim rs As Recordset Sheets("Sheet1").Select Range("A1").Select Dim DATA As String DATA = "SELECT latest.master_id, " _ & "SUBSTRING(latestBMI,1,10) eventdate, " _ & "SUBSTRING(latestBMI,12,CHARINDEX('|',latestBMI,RIGHT(latestBMI,7)) weight, " _ & "SUBSTRING(latestBMI,20,4) BMI " _ & "FROM ( " _ & "SELECT master_id, " _ & "MAX(CAST(eventdate AS VARCHAR(10)) + '|' + RIGHT(weightkg,7)+ '|' + RIGHT(bmi,4)) AS latestBMI " _ & "FROM weight " _ & "GROUP BY master_id) as latest " _ & "LEFT JOIN person p on latest.master_id = p.entity_id " Set rs = conn.Execute(DATA) With ActiveSheet.QueryTables.Add(Connection:=rs, Destination:=Range("A1")) .Refresh End With
如何使用管道分隔符将它们分成3个单独的列?
答案 0 :(得分:1)
我假设你的桌子有4列
master_id,BMI1,BMI2,BMI3和BMI4
您可以使用以下查询生成INSERT语句,然后在数据库上运行它们
select 'insert into newTable (master_id, BMI1, BMI2, BMI3) values( ' +
cast(master_id as varchar) + ',''' + replace(latestBMI, '|', ''',''') + ''')'
from #t
它生成以下语句(使用您的示例数据)
insert into newTable (master_id, BMI1, BMI2, BMI3) values( 251,'2008-05-08','84','26.8')
insert into newTable (master_id, BMI1, BMI2, BMI3) values( 2848,'1992-11-23','86.71','27.3')
insert into newTable (master_id, BMI1, BMI2, BMI3) values( 2026,'2002-04-16','105','31.6')
insert into newTable (master_id, BMI1, BMI2, BMI3) values( 22316,'2014-02-28','107.955','35.1')
insert into newTable (master_id, BMI1, BMI2, BMI3) values( 16633,'2005-07-04','70','25')
insert into newTable (master_id, BMI1, BMI2, BMI3) values( 9545,'1997-04-08','82.73','24.9')
如果列不是整数,则可以修改SELECT语句以获得所需的内容。但是,即使您的列是数字的,生成的INSERT仍然有效。
答案 1 :(得分:0)
在导入数据的代码之后,只需使用text to columns将其分开。
Sub SepDelCol()
Columns("B:B").Select
Selection.TextToColumns _
Destination:=Range("B:B"), _
DataType:=xlDelimited, _
TextQualifier:=xlDoubleQuote, ConsecutiveDelimiter:=False, _
Tab:=False, Semicolon:=False, Comma:=False, Space:=False, _
Other:=True, OtherChar:="|"
End Sub
答案 2 :(得分:0)
如果您可以先获取数据,然后在表格中将其拆分,请尝试此操作(如果您知道最新的BMI数据将在B2:B7范围内)
Selection.TextToColumns目的地:=范围(“B2:B7”),_
DataType:= xlDelimited,_
TextQualifier:= xlDoubleQuote,_
ConsecutiveDelimiter:= False,_
Tab:= False,_
分号:=假,逗号:=假,空格:=假,其他:=真,_
OtherChar:=“|”,_
FieldInfo:= Array(Array(1,1),Array(2,1),Array(3,1)),_
TrailingMinusNumbers:=真
答案 3 :(得分:0)
有各种复杂的基于SQL /数据库的解决方案(请参阅Split Strings the Right Way),在SQL语句完成后,它将更容易在VBA中处理您的数据。
您的代码看起来会产生如下所示的结果:
因此,您应该遍历B列中的结果并将其分开。
Option Explicit
Sub test()
SeparateFields ActiveSheet
End Sub
Sub SeparateFields(ws As Worksheet)
'--- assumes your concatenated field (after your SQL
' statement) ends up in column B. The separated
' fields go in columns B, C, D.
Dim concatFields As String
Dim fields() As String
Dim numRows As Long
Dim i As Long
numRows = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row
For i = 2 To numRows
concatFields = ws.Cells(i, 2).value
fields = Split(concatFields, "|", , vbTextCompare)
ws.Cells(i, 2).value = fields(0)
ws.Cells(i, 3).value = fields(1)
ws.Cells(i, 4).value = fields(2)
Next i
End Sub