Access Application.SaveAsText Đọc các giá trị Hex

Sep 11 2020

Tôi đã xuất một số đối tượng Access sang tệp văn bản bằng application.saveastext trong ứng dụng VB.net. Tôi đang sử dụng Microsoft.Interop để thực hiện điều này. Lý tưởng nhất là tôi đang tìm cách đọc qua (các) tệp văn bản kết quả bao gồm các phần thập lục phân.

Tôi hiểu cách tải từ văn bản bằng các tệp đó trong Access nhưng tôi đang hỏi về cách đọc các giá trị hex trong các tệp đó một cách tách biệt trong ứng dụng vb.net. Một chuỗi hex mẫu trong một trong các tệp trông như thế này.

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

Tại thời điểm này, những gì tôi đã thử làm là sử dụng một số bộ giải mã trực tuyến để xem liệu tôi có thể dễ dàng chuyển đổi chúng thành một chuỗi hay không. Những gì tôi nhận được thay vào đó là các ký tự đặc biệt và văn bản không thể đọc được. Tôi đã tìm kiếm nhiều chủ đề khác nhau liên quan đến application.saveastext nhưng Microsoft thực sự thậm chí không ghi lại quá trình đó và tôi không thấy bất cứ điều gì sâu rộng về chủ đề này.

Có ai có kinh nghiệm với điều này hoặc có thể chỉ cho tôi một hướng?

Trả lời

1 Heinzi Nov 03 2020 at 15:47

Làm thế nào để giải mã các khối chữ số hex?

Tóm lại: Tách chúng thành các khối của hai nhân vật ( 0x5b0046-> 5b, 00, 46, ...) và sau đó phân tích chúng thành một mảng byte. Đây là mã chúng tôi sử dụng để làm điều đó:

''' <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

Và đây là StringTools.SplitOnLengthphương pháp trợ giúp được sử dụng:

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

Và những mảng byte này có nghĩa là gì?

Nó phụ thuộc. Đây là những gì chúng tôi đã tìm ra cho đến nay:

  • PrtDevNames / PrtDevNamesW là phiên bản ANSI / Unicode của cấu trúc DEVNAMES .
  • PrtDevMode / PrtDevModeW là phiên bản ANSI / Unicode của cấu trúc DEVMODE .

Điều gì về ConditionalFormat và ConditionalFormat14? Thật không may, chúng dường như chứa một số cấu trúc dữ liệu nhị phân không có tài liệu. Ba năm trước, tôi đã hỏi về vấn đề này trên diễn đàn Access for Developers của MSDN, nhưng nhân viên Microsoft chỉ lịch sự bảo tôi bị lạc.

Chúng tôi đã giải quyết vấn đề này bằng cách cấm nội bộ nhà phát triển Access đặt định dạng có điều kiện trong trình thiết kế Biểu mẫu Access và buộc họ phải sử dụng mã VBA thay thế (tức là đặt thuộc FormatConditionstính theo cách thủ công trong mã). Đây có thể là giải pháp phù hợp cho bạn hoặc không, tùy thuộc vào kích thước của cơ sở mã kế thừa của bạn.

ComputerVersteher Sep 11 2020 at 09:21

Hãy xem Lấy tên điều khiển của biểu mẫu và báo cáo MS-Access và Tổng quan nhanh về SaveAsText và LoadFromText .

Cấu trúc dường như là:

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

Thuộc tính PrtMip trong Visual Basic đặt hoặc trả về thông tin chế độ thiết bị được chỉ định cho biểu mẫu hoặc báo cáo trong hộp thoại In.

Giải mã thuộc ConditionalFormattính có vẻ khó so với việc chỉ lặp lại Kiểm soát biểu mẫu-Bộ sưu tập và kiểm tra thuộc FormatConditionstính .

Có thể giống như (mã c # bị đánh cắp ở đây ):

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();