VBA将Access数据库导出到Excel

时间:2017-12-10 19:38:22

标签: sql excel-vba ms-access nested-loops vba

我最近建立了一个MS Access数据库,希望能够简化一些基于纸张的流程。我之前从未使用Access或在VBA中进行任何编码,所以如果我的代码看起来很糟糕,请提前道歉。

数据库正在按预期工作,现在我正在努力将一些管理报告导出到Excel。管理团队希望将数据导出到特定格式的Excel工作表而不是Access报告。

enter image description here

导出与此表单上的测试按钮的onClick事件相关联

enter image description here

这个想法是表单子表单中显示的每个独特设备都记录在单元格[C7:C14]中,理论上永远不会有超过8个独特的设备要记录。注意:我实际上并没有针对子窗体运行任何代码,我一直在使用其他表来获取我需要的数据,使用表单上的值作为键。

我已经能够获得以下代码来正确执行此操作

tagNo = """" + Tag_Number.Value + """"
EqSQL = "SELECT Equipment.Equipment_Name,Equipment.Tag_No FROM Equipment WHERE (((Equipment.Tag_No)=" & tagNo & "))"
EquipmentCell = 7
ResponseCell = 7

Set db = CurrentDb
Set rs = db.OpenRecordset(EqSQL, dbOpenDynaset, dbSeeChanges)

Do Until rs.EOF
    EquipmentCellSt = ("c" & EquipmentCell)
    With wsheet
      .Range(EquipmentCellSt).Value = rs![Equipment_Name]
    End With
    EquipmentCell = (EquipmentCell + 1)
    rs.MoveNext
Loop

下一个任务是导出响应值,因此第一件设备需要将所有响应值按顺序插入[J7:AF7],将下一个设备插入[J8:AF8]等等上。

我有一个名为 Inspection_Detail 的表,它通过子表单更新,并保存我认为我应该需要的所有数据。

到目前为止,我的想法是我需要在当前循环中嵌套另一个循环并执行一个提取响应值的SQL查询,但对于我的生活,我无法弄明白。

我编写了一个SQL查询来获取正确的记录(某些值现在是硬代码)

SELECT Export_Table.Equipment_Name, Export_Table.Task_No,
       Export_Table.Response, Export_Table.Notes, Export_Table.Tag_No
FROM Export_Table
WHERE (((Export_Table.Equipment_Name)="Pipe") 
  AND  ((Export_Table.Task_No)="A.1 Equipment") 
  AND  ((Export_Table.Tag_No)="scriptTest"));

我不确定如何构建一个循环计数器来迭代[J*:AF*]并且我不知道如何从SQL查询中提取响应值

道歉,如果我错过任何重要的事情,或者只是没有意义,我整个周末都被困在这里,我的大脑被炸了。

2 个答案:

答案 0 :(得分:2)

实际上,您可能只需要C7上的crosstab query然后CopyRecordset,填写空白列以对应Excel格式:

交叉表查询

TRANSFORM MAX(e.Response) AS Response_Value
SELECT e.Equipment_Name, '' AS BlankD, '' AS BlankE, '' AS BlankF,
                         '' AS BlankG, '' AS BlankH, '' AS BlankI
FROM Export_Table e
WHERE e.Tag_No = 'ScriptTest'
GROUP BY e.Equipment_Name 
PIVOT e.Task_No

(由于合并的单元格可能会缩短空白列,您可能需要LEFT JOIN在详尽的Task_No列表中查找表格,以填写所有需要的Excel单元格,即使NULL

<强> VBA

Set db = CurrentDb
Set rs = db.OpenRecordset("CrossTabQuery")

With wsheet
    .Range("C7").CopyFromRecordset rs
End With

rs.Close()
Set rs = Nothing
Set db = Nothing

对于动态查询,请使用QueryDefs参数化:

<强> SQL

PARAMETERS Tag_No_Param TEXT;
TRANSFORM MAX(e.Response) AS Response_Value
SELECT e.Equipment_Name, '' AS BlankD, '' AS BlankE, '' AS BlankF,
                         '' AS BlankG, '' AS BlankH, '' AS BlankI
FROM Export_Table e
WHERE e.Tag_No = [Tag_No_Param]
GROUP BY e.Equipment_Name 
PIVOT e.Task_No

<强> VBA

Dim db As Database
Dim qdef As QueryDef, rs As Recordset

Set db = CurrentDb
Set qdef = db.QueryDefs("CrossTabQuery")
qdef![Tag_No_Param] = "ScriptTest"           ' DYNAMIC VALUE

Set rs = qdef.OpenRecordset()

With wsheet
    .Range("C7").CopyFromRecordset rs
End With

rs.Close()
Set rs = Nothing
Set qdef = Nothing
Set db = Nothing

答案 1 :(得分:1)

以示例作为指南,我假设任务将始终是顺序的(无间隙),但并非所有任务始终都有响应。该示例仅显示设备组中可能的9个中的1到5个,以及安装组中可能的12个中只有1到3个。看看这是否让你接近:

Dim rsResp As DAO.Recordset
Dim Row As Integer, Col As Integer

Row = 7
Col = 2

With wsheet
.Cells(Row, Col).value = rsEquip![Tag_No]
Col = 10
Set rsResp = CurrentDb.OpenRecordset("SELECT Response FROM Export_Table ORDER BY Task_No " & _
                "WHERE Task_No LIKE 'A*' AND Tag_No = '" & Me.Tag_No & "';")
While Not rsResp.EOF
    .Cells(Row, Col).value = rsResp!Response
    rsResp.Next
    Col = Col + 1
Wend
rsResp.Close
Set rsResp = CurrentDb.OpenRecordset("SELECT Response FROM Export_Table ORDER BY Task_No " & _
                "WHERE Task_No LIKE 'B*' AND Tag_No = '" & Me.Tag_No & "';")
Col = 19
While Not rsResp.EOF
    .Cells(Row, Col).value = rsResp!Response
    rsResp.Next
    Col = Col + 1
Wend
rsResp.Close
Set rsResp = CurrentDb.OpenRecordset("SELECT Response FROM Export_Table ORDER BY Task_No " & _
                "WHERE Task_No LIKE 'C*' AND Tag_No = '" & Me.Tag_No & "';")
Col = 31
While Not rsResp.EOF
    .Cells(Row, Col).value = rsResp!Response
    rsResp.Next
    Col = Col + 1
Wend
Row = Row + 1
Col = 2
rsResp.Close
rsEquip.MoveNext

但是,工作表只允许8个Item行。看起来需要一些代码来确定在记录集中检索多少项并插入适当数量的行。