Application.SaveAsText Hex değerlerini oku

Sep 11 2020

Bir VB.net uygulaması içinde application.saveastext kullanarak birkaç Access nesnesini metin dosyalarına aktardım. Bunu başarmak için Microsoft.Interop kullanıyorum. İdeal olarak, onaltılık kısımlar dahil olmak üzere ortaya çıkan metin dosyalarını okumak istiyorum.

Access'te bu dosyaları kullanarak metinden nasıl yükleneceğini anlıyorum, ancak bir vb.net uygulamasında bu dosyalardaki onaltılık değerlerin ayrı ayrı nasıl okunacağını soruyorum. Dosyalardan birinin içindeki örnek bir onaltılık dize şuna benzer.

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

Bu noktada yapmaya çalıştığım şey, bazı çevrimiçi kod çözücüleri kullanarak onları kolayca bir dizeye dönüştürebilecek miyim diye görmek. Bunun yerine özel karakterler ve okunamayan metinler alıyorum. Application.saveastext ile ilgili çeşitli konuları kapsamlı bir şekilde araştırdım, ancak Microsoft bu süreci gerçekten belgelemedi ve konuyla ilgili kapsamlı bir şey görmüyorum.

Bununla ilgili deneyimi olan veya beni bir yöne yönlendirebilecek var mı?

Yanıtlar

1 Heinzi Nov 03 2020 at 15:47

Bu onaltılık basamak bloklarının kodu nasıl çözülür?

(Bölünmüş onları iki karakter bloklar halinde: Özetle 0x5b0046-> 5b, 00, 46bir bayt dizisi ve sonra onları ayrıştırmak, ...). İşte bunu yapmak için kullandığımız kod:

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

Ve işte StringTools.SplitOnLengthkullanılan yardımcı yöntem:

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

Ve bu bayt dizileri ne anlama geliyor?

Duruma göre değişir. Şimdiye kadar anladığımız şey buydu:

  • PrtDevNames / PrtDevNamesW, DEVNAMES yapısının ANSI / Unicode sürümleridir .
  • PrtDevMode / PrtDevModeW, DEVMODE yapısının ANSI / Unicode sürümleridir .

ConditionalFormat ve ConditionalFormat14 ne olacak? Ne yazık ki, bazı belgelenmemiş ikili veri yapısı içeriyor gibi görünüyorlar. Üç yıl önce, MSDN'nin Geliştiricilere Erişim forumunda bunu sordum , ancak Microsoft çalışanı kibarca bana kaybolmamı söyledi.

Bu sorunu, Access geliştiricilerin Erişim Formu tasarımcısında koşullu biçimlendirme ayarlamasını dahili olarak yasaklayarak ve onları bunun yerine VBA kodunu kullanmaya zorlayarak (yani, FormatConditionsözelliği kodda manuel olarak ayarlayarak ) çözdük . Eski kod tabanınızın boyutuna bağlı olarak, bu sizin için uygun bir çözüm olabilir veya olmayabilir.

ComputerVersteher Sep 11 2020 at 09:21

MS-Access formlarının ve raporlarının denetim adlarına ve SaveAsText ve LoadFromText'e Hızlı Genel Bakış konularına bir göz atın .

Yapı şöyle görünüyor:

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

Visual Basic'teki PrtMip özelliği , Yazdır iletişim kutusunda bir form veya rapor için belirtilen aygıt modu bilgilerini ayarlar veya döndürür.

Kod çözme ConditionalFormatözelliği, yalnızca Forms Controls-Collection döngüsüne ve FormatConditionsözelliği incelemeye kıyasla zor görünüyor .

Şunun gibi olabilir (c # kodu burada çalındı ):

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