【问题标题】:Access Application.SaveAsText Read Hex values访问 Application.SaveAsText 读取十六进制值
【发布时间】:2020-09-11 00:15:21
【问题描述】:

我已经使用 VB.net 应用程序中的 application.saveastext 将几个 Access 对象导出到文本文件。我正在使用 Microsoft.Interop 来完成此操作。理想情况下,我希望通读生成的文本文件,包括十六进制部分。

我了解如何使用 Access 中的这些文件从文本加载,但我正在询问如何在 vb.net 应用程序中单独读取这些文件中的十六进制值。其中一个文件中的示例十六进制字符串如下所示。

Begin TextBox
                Enabled = NotDefault
                Locked = NotDefault
                TabStop = NotDefault
                OverlapFlags =85
                IMESentenceMode =3
                Left =4770
                Top =30
                Width =1080
                Height =345
                TabIndex =3
                Name ="Qty Available"
                ControlSource ="Qty Available"
                Format ="General Number"
                EventProcPrefix ="Qty_Available"
                ConditionalFormat = Begin
                    0x0100000090000000010000000000000005000000000000001700000001000000 ,
                    0xff000000ffffff00000000000000000000000000000000000000000000000000 ,
                    0x0000000000000000000000000000000000000000000000000000000000000000 ,
                    0x5b0046006f0072006d005d0021005b00520065006f0072006400650072002000 ,
                    0x4c006500760065006c005d0000000000
                End
                GUID = Begin
                    0x992063bfd02642489a85ffd951279cb6
                End
                ColumnGroup =3
                GroupTable =6
                HorizontalAnchor =1
                IMEMode =0
            End

此时我尝试使用一些在线解码器来查看是否可以轻松地将它们转换为字符串。我得到的是特殊字符和不可读的文本。我已经对与 application.saveastext 相关的各种主题进行了广泛搜索,但 Microsoft 甚至没有记录该过程,而且我没有看到任何关于该主题的广泛内容。

有没有人有这方面的经验或者可以指点我一个方向?

【问题讨论】:

  • 道歉我正在尝试具体说明我的要求,而不添加一堆不相关的信息。我以为我概述了我的问题,我只包括了我要解码的二进制块。为了进一步回答您在文本文件上方的评论,包括控件名称及其属性。但是,如果有条件格式,它会像我发布的那样将它放在一个块中。
  • k,已更新以显示该文本框文件中的代码。
  • 为什么不导出整个表单?我的答案中的 Controls col 循环怎么样?仍然没有注意到您对条件格式的关注。
  • 条件格式的最后两行看起来像 UTF-16 编码的文本。

标签: vb.net hex ms-access-2010


【解决方案1】:

如何解码这些十六进制数字块?

简而言之:将它们分成两个字符的块(0x5b0046 -> 5b0046、...),然后将它们解析为字节数组。这是我们用来执行此操作的代码:

''' <summary>
''' Parses binary data formatted as follows:
'''     0x.... ,
'''     0x.... ,
'''     0x..
''' </summary>
Public Shared Function ParseBinaryData(lines As IEnumerable(Of String)) As Byte()
    Dim colBytes As New List(Of Byte)()

    For Each sLine In lines
        sLine = sLine.TrimStart(" "c).TrimEnd({vbCr(0), vbLf(0), ","c, " "c})
        If Not sLine.StartsWith("0x") Then
            Throw New FormatException($"Line does not start with 0x: {sLine}.")
        End If

        For Each sPair In StringTools.SplitOnLength(sLine, 2).Skip(1)
            colBytes.Add(Convert.ToByte(sPair, 16))
        Next
    Next

    Return colBytes.ToArray()
End Function

这是使用的 StringTools.SplitOnLength 辅助方法:

Public Shared Iterator Function SplitOnLength(s As String, iSegmentLength As Integer) As IEnumerable(Of String)
    s = If(s, "")
    If iSegmentLength < 1 Then Throw New ArgumentOutOfRangeException("iSegmentLength")

    While s <> ""
        Yield Left(s, iSegmentLength)
        s = Mid(s, iSegmentLength + 1)
    End While
End Function

这些字节数组是什么意思?

这取决于。到目前为止,这是我们发现的:

ConditionalFormat 和 ConditionalFormat14 呢?不幸的是,它们似乎包含一些未记录的二进制数据结构。三年前,我在 MSDN 的 Access for Developers 论坛上asked about this,但微软员工只是礼貌地告诉我不要走开。

我们通过内部禁止 Access 开发人员在 Access 表单设计器中设置条件格式并强制他们改用 VBA 代码(即在代码中手动设置 FormatConditions 属性)解决了这个问题。这可能适合您,也可能不适合您,具体取决于您的旧代码库的大小。

【讨论】:

    【解决方案2】:

    看看Get control names of MS-Access forms & reportsQuick Overview of SaveAsText and LoadFromText

    结构似乎是:

    Begin {control-class-name}
        {property-name} = {value}
    End
    CodeBehindForm
    {attributes}
    {declarations}
    {body}
    

    Visual Basic 中的PrtMip property 设置或返回为“打印”对话框中的表单或报表指定的设备模式信息。

    与仅循环 Forms Controls-Collection 并检查 FormatConditions property 相比,解码 ConditionalFormat 属性似乎很难。

    可能是这样的(c#代码被盗here):

    var objAccess = new Microsoft.Office.Interop.Access.Application();
        objAccess.OpenCurrentDatabase(@"C:\Users\Public\Database1.accdb");
    
        string formName = "ClientForm";
        objAccess.DoCmd.OpenForm(formName, Microsoft.Office.Interop.Access.AcFormView.acDesign);
        Microsoft.Office.Interop.Access.Form frm = objAccess.Forms[formName];
    
        Console.WriteLine(String.Format("The FormHeader section of form [{0}] contains the following controls:", formName));
        foreach (Microsoft.Office.Interop.Access.Control ctl in frm.Controls)
        {
            foreach (Microsoft.Office.Interop.Access.FormatCondition fc in ctl.FormatConditions)
            {
                //read  FormatCondition properties here https://docs.microsoft.com/en-us/office/vba/api/access.formatcondition
                Console.WriteLine();
                Console.WriteLine(String.Format("    [{0}]", ctl.Name));
                Console.WriteLine(String.Format("        {0}", ctl.GetType()));
                Console.WriteLine(String.Format("           {0}", fc.Backcolor));
                ...
                Console.WriteLine(String.Format("           {0}", fc.Type));
            }
        }
        objAccess.DoCmd.Close(Microsoft.Office.Interop.Access.AcObjectType.acForm, formName);
        objAccess.CloseCurrentDatabase();
        objAccess.Quit();
    

    【讨论】:

    • 谢谢,我确实在 GitHub 上看到过这个,以及关于 so 的文章。我遇到的问题是将那段 vba 代码转换为 vb.net,并且仅用于 sn-p 而不是整个文件,或者像在该示例中那样在 Access 中调用它。我要解码的主要部分是条件格式部分,在我的原始帖子中进行了更新。我不关心的其他十六进制或二进制块。虽然破解一个应该破解其他。
    • 酷豆。我稍后再看一下。感谢您的帮助
    猜你喜欢
    • 2016-03-21
    • 1970-01-01
    • 2015-01-26
    • 1970-01-01
    • 2010-12-07
    • 2014-02-25
    • 2014-02-18
    • 2018-07-26
    • 1970-01-01
    相关资源
    最近更新 更多