簡體   English   中英

使用VB代碼在Access中轉置表

[英]Transpose a table in Access using VB code

我有一個表,其中填充了定界文本文件中的數據。 數據來自另一個系統,我無法修改將其生成為要導入的文本文件的方式。 將數據導入訪問后,就不能以標准化的方式進行訪問。 數據的前兩列是日期范圍,第三列是位置代碼,其余54列包含每個位置的特定數據。 我需要找到每個記錄的前五個值,以便可以將它們放入報告中。

我在另一個線程中提出了這個問題,但是找不到解決方案。 在那個線程中,有人建議我使用聯合查詢。 看來它可以完美運行,但是您只能在訪問中使用50個聯合,而且我必須訪問許多領域。

現在,我試圖在訪問中使用VB代碼來轉置表。 我正在使用從此頁面檢索到的以下代碼。 它在執行時引發錯誤。 我不知道是什么問題。 我知道這是語法錯誤或創建對象,但是我已經嘗試了所有我能想到的並且無法使它正常工作。 另外,列標題將包含字符串信息,因此我要將變量更改為變量而不是整數? 此代碼的任何幫助,或有關如何從表中獲取我想要的東西的建議,將不勝感激。

實際表的圖片。

我收到一個錯誤->'運行時錯誤'3265':在此集合中找不到該項目。

Private Sub Command78_Click()


  Const cstrInputTable = "Base Period OT"
  Const cstrOutputTable As String = "Normalized Base Period OT"

  Dim dbs As DAO.Database
  Dim rstInput As DAO.Recordset
  Dim rstOutput As DAO.Recordset
  Dim intYear As Integer

  Set dbs = CurrentDb
  Set rstInput = dbs.OpenRecordset(cstrInputTable)
  Set rstOutput = dbs.OpenRecordset(cstrOutputTable)

  If Not rstInput.EOF Then
    ' For each column in the Input table, create a record in the output   table
    For intYear = 1990 To 2011
      rstInput.MoveFirst
      rstOutput.AddNew
        rstOutput![Year] = intYear

        ' Go through every record in the Input table
        Do
          rstOutput(rstInput![Data Type]) = rstInput(CStr(intYear))
          rstInput.MoveNext
        Loop Until rstInput.EOF

      rstOutput.Update
    Next intYear
  End If
  rstInput.Close
  rstOutput.Close
  dbs.Close

  MsgBox "Data Successfully Transformed"
  DoCmd.OpenTable cstrOutputTable

End Sub

仍然不確定我是否完全理解您的輸入和輸出。 不過,我會嘗試一下,如果我與您要尋找的內容接近,您會告訴我。

您可以創建僅包含3個字段的“臨時”表,僅用於排序目的。 然后,您可以遍歷源表並將“位置”,“列標題”(3個字母代碼)和每個字段的值添加到“臨時”表中。

然后,您可以按值DESC排序並選擇前5名。

Public Sub GetTopFive()
    On Error GoTo ErrProc

    Dim rs As DAO.Recordset
    Set rs = CurrentDb.OpenRecordset("SELECT Location, AMR, AXT, BRM, BMM, CSR, CTC " & _
                                     "FROM DataSource ORDER BY Location;", dbOpenSnapshot)

    If rs.EOF Then GoTo Leave
    With rs
        .MoveLast
        .MoveFirst
    End With

    Dim idx As Long
    For idx = 1 To rs.RecordCount
            AddToTempTable rs
           'Now the Temp table holds one Location, sorted by value
           'Selecting the top 5 records will give you what you're looking for
           'If that's the case, provide additional info on how to handle this 
           'as each location might have different field names.
        rs.MoveNext
    Next idx


Leave:
    On Error Resume Next
    rs.Close
    Set rs = Nothing
    On Error GoTo 0
    Exit Sub

ErrProc:
    MsgBox Err.Description, vbCritical
    Resume Leave
End Sub

'Add To Temp for sorting
Private Sub AddToTempTable(rs As DAO.Recordset)

    Dim fld As DAO.Field
    For Each fld In rs.Fields
        If fld.Name <> "Location" Then
            With CurrentDb.QueryDefs("qryAddToTemp")
                .Parameters("[prmLocation]").Value = rs!Location
                .Parameters("[prmFileldName]").Value = fld.Name
                .Parameters("[prmFieldValue]").Value = fld.Value
                .Execute dbFailOnError
            End With
        End If
    Next fld
End Sub

導入查詢

PARAMETERS [prmLocation] Text ( 255 ), [prmFileldName] Text ( 255 ), [prmFieldValue] IEEESingle;
INSERT INTO tbTemp ( Location, [Field Name], [Field Value] )
SELECT [prmLocation] AS Location, [prmFileldName] AS [Field Name], [prmFieldValue] AS [Field Value];

臨時表

臨時表

更新:

Public Sub GetTopFive()
    On Error GoTo ErrProc

    Dim rs As DAO.Recordset
    Set rs = CurrentDb.OpenRecordset("SELECT Location, AMR, AXT, BRM, BMM, CSR, CTC " & _
                                     "FROM DataSource ORDER BY Location;", dbOpenSnapshot)

    If rs.EOF Then GoTo Leave
    With rs
        .MoveLast
        .MoveFirst
    End With

    Dim rsTemp As DAO.Recordset, fld As DAO.Field, idx As Long
    Set rsTemp = CurrentDb.OpenRecordset("tbTemp")

    With rsTemp
        For idx = 1 To rs.RecordCount
            For Each fld In rs.Fields
                If fld.Name <> "Location" Then
                    .AddNew
                    .Fields("YourCodeColumnName").Value = fld.Name
                    .Fields(rs!Location).Value = fld.Value
                    .Update
                End If
            Next fld
            rs.MoveNext
        Next idx
    End With

Leave:
    On Error Resume Next
    rsTemp.Close
    Set rsTemp = Nothing
    rs.Close
    Set rs = Nothing
    On Error GoTo 0
    Exit Sub

ErrProc:
    MsgBox Err.Description, vbCritical
    Resume Leave
End Sub

根據所提供的信息,一旦了解了DAO Recordset對象的工作方式以及它們在“表”中所引用的字段,就可以從6265處獲得3265錯誤的可能性,其中4種具有相同的解決方案。

給定您提供的代碼, Item not found in this collection錯誤Item not found in this collection ,表示您正在引用的記錄集中的字段名(列名)不存在。 或者,您正在引用數據庫中不存在的表名。

由於您的代碼是動態確定字段名稱的,並且您沒有提供表Base Period OTNormalized Base Period OT的表結構,因此您必須自己弄清楚其中的一部分。

這是Recordset對象可能出現的錯誤以及您要查找的4個地方:

  1. rstOutput![Year] = intYear ,您要告訴Access您希望表Normalized Base Period OT存在一個名為“ Year”的列,並且您希望將intYear的當前值插入該列中。 如果“ Year”不是該表中的列名,則可能是問題所在。

  2. rstOutput(rstInput![Data Type]) = rstInput(CStr(intYear))在此單行代碼中,您有3個可能的錯誤位置。

    一種。 rstInput![Data Type]Base Period OT是否包含名為“數據類型”的列? 如果不是,這將是一個錯誤。 在這里,您靜態地提供了您希望在輸入表中存在的列的名稱。

    b。 rstOutput(rstInput![Data Type])假設rstInput![Data Type]是有效的列,那么該列中的值現在就是您希望存在於Normalized Base Period OT中的列的名稱。 如果那不是真的,那將是一個錯誤。 在這里,您正在動態提供您希望在輸出表中存在的列的名稱。

    C。 rstInput(CStr(intYear))表“ Base Period OT是否包含intYear當前值的intYear (即該表是否包含循環中定義的名為1990、1991、1992等至2011的列?)將是一個錯誤。 再次在這里,您將動態提供您希望在輸入表中存在的列的名稱。

5&6。如果在兩個常量中命名的表不存在,您還可能在OpenRecordset命令上收到此錯誤。

這解決了您的代碼示例的問題,但是由於我們沒有足夠的附加信息,因此未解決您為其他指定目的轉換數據的方法是否正確。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM