MS-Access使用VBA将可变行值动态转换为可变列值

约翰

原始代码链接MS Access-将行值转换为列值

我有一个跟进的问题,答案没有完全解决,但很快就解决了。上面原始代码链接中询问了它实际上,这是网络上的单个页面,该问题专门针对动态地使用VBA解决了将一对多关系列中的多个值转换为每个相关值的单个行的问题在此站点上已经询问过该问题的变体大约十二次,并且从字面上看,没有一个答案能像Vlado(回答问题的用户)那样远,这是解决此问题的必要条件。

我接受了Vlado在该链接中发布的内容,根据我的需要对其进行了调整,进行了一些基本的清理,解决了所有的故障排除和语法问题(甚至删除了一个声明未使用的变量:f As Variant),然后发现它几乎可以一直工作。它正确地产生与值表的前两列,正确使用迭代变量头数列的正确数量,但无法填充值的细胞每一个相关的“多值”的。很近!

为了达到目的,我必须注释掉db.Execute Transpose Function的updateSql部分;从末到第三排。如果我不对此进行注释,它仍会生成表,但会引发运行时错误3144(UPDATE语句中的语法错误),并且仅创建第一行和所有具有正确标题的正确列(但仍然无效)单元格中的值)。下面是上面链接中的Vlado代码,但根据我的字段名称需要进行了调整,并在定义的两个Function的每个函数的开头设置了变量。第二个功能肯定可以正常工作。

Public Function Transpose()

    Dim DestinationCount As Integer, i As Integer
    Dim sql As String, insSql As String, fieldsSql As String, updateSql As String, updateSql2 As String
    Dim db As DAO.Database, rs As DAO.Recordset, grp As DAO.Recordset
    Dim tempTable As String, myTable As String
    Dim Var1 As String, Var2 As String, Var3 As String, Var4 As String

    tempTable = "Transposed"        'Value for Table to be created with results
    myTable = "ConvergeCombined"    'Value for Table or Query Source with Rows and Columns to Transpose
    Var1 = "Source"                 'Value for Main Rows
    Var2 = "Thru"                   'Value for Additional Rows
    Var3 = "Destination"            'Value for Columns (Convert from Rows to Columns)
    Var4 = "Dest"                   'Value for Column Name Prefixes

    DestinationCount = GetMaxDestination
    Set db = CurrentDb()
    If Not IsNull(DLookup("Name", "MSysObjects", "Name='" & tempTable & "'")) Then
        DoCmd.DeleteObject acTable, tempTable
    End If

    fieldsSql = ""
    sql = "CREATE TABLE " & tempTable & " (" & Var1 & " CHAR," & Var2 & " CHAR "
    For i = 1 To DestinationCount
        fieldsSql = fieldsSql & ", " & Var4 & "" & i & " INTEGER"
    Next i
    sql = sql & fieldsSql & ")"
    db.Execute (sql)

    insSql = "INSERT INTO " & tempTable & " (" & Var1 & ", " & Var2 & ") VALUES ("
    Set grp = db.OpenRecordset("SELECT DISTINCT " & Var1 & ", " & Var2 & " FROM " & myTable & " GROUP BY " & Var1 & ", " & Var2 & "")
    grp.MoveFirst

    Do While Not grp.EOF
        sql = "'" & grp(0) & "','" & grp(1) & "')"
        db.Execute insSql & sql
        
        Set rs = db.OpenRecordset("SELECT * FROM " & myTable & " WHERE " & Var1 & " = '" & grp(0) & "' AND " & Var2 & " = '" & grp(1) & "'")
        updateSql = "UPDATE " & tempTable & " SET "
        updateSql2 = ""
        i = 0
        rs.MoveFirst

        Do While Not rs.EOF
            i = i + 1
            updateSql2 = updateSql2 & "" & Var3 & "" & i & " = " & rs(2) & ", " ' <------- MADE CHANGE FROM (3) to (2)
            rs.MoveNext
        Loop

        updateSql = updateSql & Left(updateSql2, Len(updateSql2) - 1) & " WHERE " & Var1 & " = '" & grp(0) & "' AND " & Var2 & " = '" & grp(1) & "'"
        db.Execute updateSql ' <-- This is the point of failure
        grp.MoveNext
    Loop
End Function

Public Function GetMaxDestination()

    Dim rst As DAO.Recordset, strSQL As String
    myTable = "ConvergeCombined"    'Value for Table or Query Source with Rows and Columns to Transpose
    Var1 = "Source"                 'Value for Main Rows
    Var2 = "Thru"                   'Value for Additional Rows
    Var3 = "Destination"            'Value for Columns (Convert from Rows to Columns)

    strSQL = "SELECT MAX(CountOfDestination) FROM (SELECT Count(" & Var3 & ") AS CountOfDestination FROM " & myTable & " GROUP BY " & Var1 & ", " & Var2 & ")"
    Set rst = CurrentDb.OpenRecordset(strSQL)
    GetMaxDestination = rst(0)
    rst.Close
    Set rst = Nothing
End Function

样品表:

样品表

样本数据:

样本数据

约翰

So with the help of a friend I figured it out. It turns out I needed two Functions because the one-to-many relationships go both directions in my case. I explain below what needs to happen in comments for this to work. Essentially I went with the second comment under the question I posed (pre-defining field names in static tables because there is a limited number of fields that any person will need - it can't exceed 256 fields anyway, but it isn't always practical to use more than a dozen or so fields - this way allows for both and at the same time to simplify the code significantly).

该解决方案实际上是有效的-但它依赖于具有标记为ConvergeSend和ConvergeReceive的表(或我所处的查询)。另外,请务必注意,目的地为单个且来源为复数的实例,表或查询(ConvergeSend / ConvergeReceive)必须具有“目的地”值作为迭代的“来源”列的最左列。其他表/查询也是如此(但反向命名约定)(“源”列必须位于“迭代的目标”列的最左)。

' For this code to work, create a table named "TransposedSend" with 8 columns: Source, Destination1, Destination2,...Destination7; OR however many you need
' Save the table, Edit it, change all field values to Number and remove the 0 as Default Value at the bottom
' Not changing the field values to Number causes the Insert Into function to append trailing spaces for no apparent reason

Public Function TransposeSend()

    Dim i As Integer
    Dim rs As DAO.Recordset, grp As DAO.Recordset

    CurrentDb.Execute "DELETE * FROM TransposedSend", dbFailOnError

    CurrentDb.Execute "INSERT INTO TransposedSend (Source) SELECT DISTINCT Source FROM ConvergeSend GROUP BY Source", dbFailOnError

    Set grp = CurrentDb.OpenRecordset("SELECT DISTINCT Source FROM ConvergeSend GROUP BY Source")
    grp.MoveFirst

    Do While Not grp.EOF
        Set rs = CurrentDb.OpenRecordset("SELECT Source, Destination, [Destination App Name] FROM ConvergeSend WHERE Source = " & grp(0))
        i = 0
        rs.MoveFirst
        Do While Not rs.EOF
            i = i + 1
            CurrentDb.Execute "UPDATE TransposedSend SET Destination" & i & " = '" & rs(1) & "', [Destination" & i & " App Name] = '" & rs(2) & "'" & " WHERE Source = " & grp(0)
            rs.MoveNext
        Loop
        grp.MoveNext
    Loop

End Function


' For this code to work, create a table named "TransposedReceive" with 8 columns: Destination, Source1, Source2,...Source7; OR however many you need
' Save the table, Edit it, change all field values to Number and remove the 0 as Default Value at the bottom
' Not changing the field values to Number causes the Insert Into function to append trailing spaces for no apparent reason

Public Function TransposeReceive()

    Dim i As Integer
    Dim rs As DAO.Recordset, grp As DAO.Recordset

    CurrentDb.Execute "DELETE * FROM TransposedReceive", dbFailOnError

    CurrentDb.Execute "INSERT INTO TransposedReceive (Destination) SELECT DISTINCT Destination FROM ConvergeReceive GROUP BY Destination", dbFailOnError

    Set grp = CurrentDb.OpenRecordset("SELECT DISTINCT Destination FROM ConvergeReceive GROUP BY Destination")
    grp.MoveFirst

    Do While Not grp.EOF
        Set rs = CurrentDb.OpenRecordset("SELECT Destination, Source, [Source App Name] FROM ConvergeReceive WHERE Destination = " & grp(0))
        i = 0
        rs.MoveFirst
        Do While Not rs.EOF
            i = i + 1
            CurrentDb.Execute "UPDATE TransposedReceive SET Source" & i & " = '" & rs(1) & "', [Source" & i & " App Name] = '" & rs(2) & "'" & " WHERE Destination = " & grp(0)
            rs.MoveNext
        Loop
        grp.MoveNext
    Loop

End Function

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

使用SQL从MS Access表中获取可变的年末日期和值

来自分类Dev

使用SQL从MS Access表中获取可变的年末日期和值

来自分类Dev

MySQL将可变列转换为行

来自分类Dev

从MS Access转换为mySQL

来自分类Dev

MS Excel:将行转换为列

来自分类Dev

在MS SQL中将行转换为列

来自分类Dev

MS Access:选择表的最大列值

来自分类Dev

使用IFF比较值的MS Access查询

来自分类Dev

MS Access VBA IF()

来自分类Dev

将可变行数转换为列

来自分类Dev

从VBA SQL语法错误将MS EXCEL转换为MS ACCESS .accdb数据库

来自分类Dev

将MS Access指向VBA中的可变路径以导出到Excel

来自分类Dev

在MS Access中将yyyymmdd数字或字符串转换为true日期值

来自分类Dev

将SQl查询转换为MS Access

来自分类Dev

将MS Access SQL转换为Oracle?

来自分类Dev

将PHP查询转换为MS Access

来自分类Dev

MS Access将.csv转换为.xls

来自分类Dev

MS Access将文本转换为缩写

来自分类Dev

如何在ms Access中搜索并替换为Null值

来自分类Dev

MS Access 2013:通过VBA使用MS Word的语法检查

来自分类Dev

(VBA)具有数千行的 Excel - 如何将可变长度的列转换为行?

来自分类Dev

MS Access 库模板 - VBA 中的参考类别值

来自分类Dev

SQL查询将行转换为MS Access表中的列

来自分类Dev

将MS SQL图像列值转换为bit或int 0/1

来自分类Dev

MS SQL. 将行转换为列

来自分类Dev

将MS转换为秒

来自分类Dev

动态MS SQL查询

来自分类Dev

MS Access日期转换错误

来自分类Dev

Int()函数MS Access VBA