【问题标题】:Better way to implement an Access 2007 "HTML Report"实现 Access 2007“HTML 报告”的更好方法
【发布时间】:2011-01-24 20:04:56
【问题描述】:

我需要制作一个类似“静态 html”的常见问题解答文档,供项目内部使用。

我将所有项目作为记录(问题、答案、类别)放入 Access 2007 数据库中,然后构建了一个报告,该报告使用子报告创建目录作为内部链接,然后列出所有问题和答案。该报告是一堆带有动态生成的 html 代码的文本区域(显然我还没有足够的信誉来发布图像,所以 http://i115.photobucket.com/albums/n299/SinbadEV/ReportCapture.png)...我只是将报告导出到一个文本文件,然后将其重命名为 . html 并在浏览器中打开。

我认为必须有一种不那么邪恶的方法来做到这一点。

【问题讨论】:

  • 好主意,因为你会遇到这种方法的问题。这个方法很聪明,我用它来生成复杂的 XML 文件,但是 Access 有一个错误:当您将报告导出为文本时,有时会交换行!它们在预览中看起来不错,但在最终的文本文件中,页面的最后一行“上升”了 2 或 4 行。并且您的 xml(在您的情况下为 html)不再有效。我最终用 VBA 重写了所有内容,回到了循环和中断的美好时光。
  • 我经常使用 HTML 使用一点 VBA 创建报告。我发现我可以在备忘录字段中将大量标准内容保存为模板,然后只需交换可变数据即可。

标签: html ms-access


【解决方案1】:

我现在使用来自 SinbadEVawrigley 的想法在 MS Access 2007 中创建具有专业外观的 HTML 报告。就我而言,我不得不使用另一个技巧:

我发现,由于 MS Access 中的一些错误,它没有正确地将报告保存为 txt 格式。有时它会丢失很多信息,即使它显示在屏幕上。我也看到了问题,这里提到有时会访问混合线。它似乎取决于几个因素,例如报告和数据是否跨越 MS Acess 报告中的页面。

但是我发现,导出到 *.rtf 确实可以正常工作。因此,方法是制作 MS Acess 报告,将其保存到文本文件中时会创建一个 HTML 代码(就像 SinbadEV 所描述的那样),但是您首先需要将其保存到 *rtf。之后,您需要使用 MS Word 自动化将 *.rtf 转换为 txt 文件,并为其赋予 .html 扩展名(实际上并不需要太多努力)。

除了 MS Word 自动化之外,您还可以使用 Doxillion Document Converter 之类的工具从命令行将 rtf 转换为文本格式。

您可以在会议记录、问题、风险、协议、行动、项目跟踪工具 (http://sourceforge.net/projects/miraapt/) 中查看具有此功能的数据库。

【讨论】:

    【解决方案2】:

    Application对象中有一个ExportXML方法,可以用XML导出数据库对象(表格、报告等)。如果要为浏览器格式化,则需要 XSL 样式表或 XSTL 文档:

    http://msdn.microsoft.com/en-us/library/bb258194(v=office.12).aspx

    我会说这是“规范”的做法。 OTOH 编写 XSL 和 XSTL 并不是一件有趣的事情,如果您的 HTML 生成器工作正常,那么您应该保持原样。 (实际上,恕我直言,这是一个不错的技巧)。

    【讨论】:

    • 虽然我可能最终决定使用我当前的方法或 VBA 代码,但这似乎是我问题的“正确”答案。该项目的优先级较低,因此我还没有开始实施任何提出的想法,但我发现一个页面专门解释了如何创建和 XSLT 为类似数据提供目录,我认为我可以对其进行改造以满足我的需求目标:dpawson.co.uk/xsl/sect2/N7402.html
    • 我目前卡在这个,示例代码不起作用,只是手动选择导出报告或查询结果会生成一个带有 dataroot 节点但不包含数据的 XML 文件。跨度>
    【解决方案3】:

    我看不出你所做的任何事情本质上是“邪恶的”。我为(现已停刊的杂志)Smart Access 写了一篇文章,出于不同的原因使用了类似的技术。 HTML 报告是副产品。从本质上讲,我的技术允许使用 Access 创建非常广泛的 word 文档,这些文档像键入的文本一样流动,而不是看起来像使用框创建的报告。

    您仍然可以阅读 MSDN 上的文章: Extending Access Reports With Word and HTML

    诀窍是使用您正在做的报告生成 HTML,然后使用自动化,在 Word 中打开 .html 文件并将其另存为 RTF。

    我们使用该技术为约克教区创建了一个 300 页的目录。它完美无缺。

    【讨论】:

      【解决方案4】:

      以防万一您想采用 VBA 方式:我编写了一些可以使其变得非常简单的函数:

      • 创建包含您要输出的数据的查询,
      • 然后打开查询并循环遍历所有记录,使用下面的函数 rRsToXml 将数据输出到文本文件。

        Option Compare Database
        Option Explicit
        
        Function fRsToXml(rs As Recordset, Optional ignorePrefix As String = "zz", _
                        Optional ignoreNulls As Boolean = False) As String
        '<description>  Returns an XML string with all fields of the current record,
        '               using field names as tags.
        '               Field names starting with "zz" (or other special prefix) are ignored</description>
        '<parameters>   rs: recordset (byRef, of course)</parameters>
        '<author>       Patrick Honorez - www.idevlop.com  </author>
            Dim f As Field, bPrefLen As Byte
            Dim strResult As String
            bPrefLen = Len(ignorePrefix)
            For Each f In rs.Fields
                If Left(f.Name, bPrefLen) <> ignorePrefix Then 'zz fields are ignored !
                    If (Not ignoreNulls) Or (ignoreNulls And Not IsNull(f.Value)) Then
                        strResult = strResult & xTag(f.Name, f.Value) & vbCrLf
                    End If
                End If
            Next f
            fRsToXml = strResult
        End Function
        
        Function xTag(ByVal sTagName As String, ByVal sValue, Optional SplitLines As Boolean = False) As String
        '<description>  Create an xml node and returns it as a string   </description>
        '<parameters>   <sTagName>  name of the tag </sTagName>
        '               <sValue>    string to embed </sValue>
        '               <SplitLine> True to include CrLf at the end of each line
        '                           (optional - default = False) </SplitLine></parameters>
        '<author>        Patrick Honorez - www.idevlop.com  </author>
        '<note>          Make sure sValue does not contains XML forbidden characters ! </note>
        '<changelog>
        '</changelog>
            Dim strNl As String, intAmp
            If SplitLines Then
                strNl = vbCrLf
            Else
                strNl = vbNullString
            End If
        
            xTag = "<" & sTagName & ">" & strNl & _
                    Nz(sValue, "") & strNl & _
                    "</" & sTagName & ">" '& strNl
        End Function
        
        Function CleanupStr(strXmlValue) As String
        '<description>  Replace forbidden char. &'"<> by their Predefined General Entities </description>
        '<author>       Patrick Honorez - www.idevlop.com  </author>
            Dim sValue As String
            If IsNull(strXmlValue) Then
                CleanupStr = ""
            Else
                sValue = CStr(strXmlValue)
                sValue = Replace(sValue, "&", "&amp;")  'do ampersand first !
                sValue = Replace(sValue, "'", "&apos;")
                sValue = Replace(sValue, """", "&quot;")
                sValue = Replace(sValue, "<", "&lt;")
                sValue = Replace(sValue, ">", "&gt;")
                CleanupStr = sValue
            End If
        End Function
        

      【讨论】:

        【解决方案5】:

        我曾经欺骗报告生成器为我制作 html 文档,但这种方法有局限性。首先,当您运行报告时,它会生成相当难看的 html,而不是可打印的报告。运行报表后还有更多工作可以将报表转换为漂亮的 html 文档,该文档可以在文字处理器中打开,然后保存为常规文档。 LibreOffice 通常比 ms-word 更适合接收生成的 html 文档,但偶尔 LibreOffice 无法完成这项工作(有一段时间它在链接图像方面存在问题)。文字处理器会忽略 css 样式,所以不要打扰样式,直接格式化仍然可以很好地工作,特别是对于文本是表格。如果所有导出的数据都在 html 表格中,那么使用 LibreOffice,因为 LibreOffice 可以根据 h1、h2、h3 标题生成目录,而 ms-word 不能。

        这些天来,我只是将整个报告编写为 VBA 标准模块中的一个过程。我仍然不使用面向对象的代码,也没有理由在这里。完全用 VBA 编写的报告可以比标准 ms-Access 报告设计器生成的复杂得多。报告设计器报告需要大量修改才能使格式正确,这会耗费时间。对于复杂的报表,VBA 方法实际上更快。用 VBA 编写的报告可以每隔一秒运行一次,因此很容易调整表格的列宽等内容,并重新运行报告以检查输出。使用 VBA 创建的 html 报告被写为 html 文件,ms-access 可以发出 shell 命令以在 Web 浏览器中打开报告。如果浏览器已打开,则新报告会在新选项卡中打开,因此您可以看到以前版本的外观,因为此版本仍将在另一个选项卡中打开。

        在标准模块(而不是表单模块)中编写报告,并从表单上的某些按钮单击事件中调用它。报告只需要被告知标题是什么,输出文件名和位置是什么以及报告应该输出的数据范围。报告过程包含创建报告所需的所有其他逻辑。以下是在我的一个应用程序中触发报告的调用过程。调用代码的目的是在分隔的文本文件中导出带有地理标记的照片列表,以便我可以在地图上绘制照片位置。导出 html 文件的过程非常相似。一些自定义函数在下面的代码中,但结构应该是可识别的。

        Private Sub cmdCSV_File_Click()
        
            Dim FolderName As String
            Dim FileName As String
            Dim ReportTitle As String
            Dim SQL As String
            Dim FixedFields As String
            Dim WhereClause As String
            Dim SortOrder As String
        
        
            'Set destination of exported data
            FolderName = InputBox("Please enter name of folder to export to", AppName, mDefaultFolder)
            If mPaths.FolderExists(FolderName).Success Then
                mDefaultFolder = FolderName  'holds default folder name in case it is needed again
            Else
                MsgBox "Can't find this folder", vbCritical, AppName
                Exit Sub
            End If
            FileName = CheckTrailingSlash(FolderName) & "PhotoPoints.txt"
        
            'Set Report Title
            If Nz(Me.chkAllProjects, 0) Then
                ReportTitle = "Photos from all Projects"
            ElseIf Nz(Me.SampleID, 0) Then
                ReportTitle = "Photos from Sample " & Me.SampleID
            ElseIf Nz(Me.SurveyID, 0) Then
                ReportTitle = "Photos from Survey " & Me.SurveyID
            ElseIf Nz(Me.ProjectID, 0) Then
                ReportTitle = "Photos from Project " & Me.ProjectID
            Else
                MsgBox "Please select a scope before pressing this button", vbExclamation, AppName
                Exit Sub
            End If
        
            'Update paths to photos
            If Have(Me.ProjectID) Then
                WhereClause = " (PhotoPath_ProjectID = " & Me.ProjectID & ")"  'also covers sample and survey level selections
            Else
                WhereClause = " True"  'when all records is selected
            End If
            Call mPhotos.UpdatePhotoPaths(WhereClause) 'refreshes current paths
        
            'Set fixed parts of SQL statement
            FixedFields = "SELECT Photos.*, PhotoPaths.PhotoPath_Alias, PhotoPaths.CurrentPath & Photos.PhotoName AS URL, " _
            & "PhotoPaths.CurrentPath & 'Thumbs\'  & Photos.PhotoName as Thumb " _
            & "FROM Photos INNER JOIN PhotoPaths ON Photos.PhotoPathID = PhotoPaths.PhotoPathID WHERE "
            SortOrder = " ORDER BY ProjectID, SurveyID, SampleID, Photo_ID"
        
            'set scope for export
            WhereClause = "(((Photos.Latitude) Between -90 And 90) AND ((Photos.Longitude) Between -180 And 180) AND ((Photos.Latitude)<>0) AND ((Photos.Longitude)<>0)) AND " & WhereClause
            SQL = FixedFields & WhereClause & SortOrder & ";"
        
            'Export data as a delimited list
            FileName = ExportCSV(FileName, SQL)
            Call OpenBrowser(FileName)
        
        End Sub
        

        下一段代码实际上写出了分隔的文本文件(html 只有标签而不是管道)。在这种情况下,竖线或竖线用于分隔值而不是逗号,因为逗号可能出现在数据中。该代码计算出自己有多少列,并将标题放在顶部。

            Public Function ExportCSV(FileAddress As Variant, SQL As String) As String
                If Not gDeveloping Then On Error GoTo procerr
        
                PushStack ("mfiles.ExportCSV")
        
                'Exports a csv file
        
                If Nz(FileAddress, "") = "" Then
                    ExportCSV = "Failed"
                    Exit Function
                End If
        
                'Create text file:
                Dim webfile As Object, w
                Set webfile = CreateObject("Scripting.FileSystemObject")
                Set w = webfile.CreateTextFile(FileAddress, True)
        
                Dim D As Database, R As Recordset, NumberOfFields As Long, Out As String, i As Long
        
                Set D = CurrentDb()
                Set R = D.OpenRecordset(SQL, dbOpenSnapshot)
                If R.RecordCount > 0 Then
                    With R
                    NumberOfFields = .Fields.Count - 1
        
                    'Field headings
                    For i = 0 To NumberOfFields
                        If i = 0 Then
                            Out = .Fields(i).Name
                        Else
                            Out = Out & "|" & .Fields(i).Name
                        End If
                    Next
                    w.writeline Out
        
                    'Field data
                    Do Until .EOF
                        For i = 0 To NumberOfFields
                        If i = 0 Then
                            Out = .Fields(i)
                        Else
                            Out = Out & "|" & .Fields(i)
                        End If
                        Next i
                        w.writeline Out
                        .MoveNext
                    Loop
                    End With
                End If
        
            Set R = Nothing
            Set D = Nothing
        
            ExportCSV = FileAddress
        
        exitproc:
                PopStack
                Exit Function
        
        procerr:
                Call NewErrorLog(Err.Number, Err.Description, gCurrentProc, FileAddress & ", " & SQL)
                Resume exitproc
        
        End Function
        

        下面是来自 openbrowser 函数的 sn-p。该函数的其余部分用于确定网络浏览器的位置,因为这取决于 Windows 的版本以及浏览器是 32 位还是 64 位。

        'Set up preferred browser
        If Right(BrowserPath, 9) = "Opera.exe" Then
            FilePrefix = "file://localhost/"
        ElseIf Right(BrowserPath, 11) = "Firefox.exe" Then
            FilePrefix = "file:///"
        Else
            FilePrefix = ""
        End If
        
        'Show report
        Instruction = BrowserPath & " " & FilePrefix & WebpageName
        TaskSuccessID = Shell(Instruction, vbMaximizedFocus)
        

        此示例包含创建 html 报告所需的大约 90% 的代码,该报告的范围由调用它的表单设置。希望这能让某人克服困难。

        【讨论】:

          猜你喜欢
          • 2011-03-21
          • 1970-01-01
          • 1970-01-01
          • 2017-11-07
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多