Application.SaveAsText Hex değerlerini oku
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
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.
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();