ist die Ausgabe von gepackten und binären Feldern in eine Datei mittels
Excel bzw. VBA möglich?
Falls ja, gibt's irgendwo Tips dazu?
Danke!
Gruß
Michael Donner
Hallo Michael,
dein Name sollte auch im From-Feld stehen, T-Online ist jemand anderes. ;-)
Es gibt tausende von Datei-Formaten. Meinst du Basic? CVI CVS und so?
Die sind sind mir neulich begegnet, weiß im Moment ab nicht wo.
--
Gruß
Matthias Tacke Email: Matt...@Tacke.de
---------+---------+---------+---------+---------+---------+---------+-------
Das mit dem "t-online" war ein Versehen - hab's geändert ;)
Leider kenn ich mich noch nicht so gut aus. CVI und CVS sagt mit nix - ich
kenn nur CSV -> comma seperated values - oder so ähnlich.
Was ich eigentlich möchte ist nicht die Ausgabe von ACSII-Zeichen sondern
von binären Werten in eine Datei.
Definition:
Die physikalische Speicherung des Binärformates erfolgt rechtsbündig als
Dualzahl (d.h das niederwertigste Bit steht ganz rechts). Negative Zahlen
werden als Komplement dargestellt.
Ich weiß nicht ob sowas überhaupt mit Excel/VBS möglich ist.
Gruß
Michael Donner
Matthias Tacke <Matt...@Tacke.de> schrieb in im Newsbeitrag:
8l2313$k8v$12$1...@news.t-online.com...
Hallo Michael,
gehen tut fast alles, ist eine Frage des Aufwandes. Ist das mit dem ge-
packten und binären Feldern nur Selbstzweck oder verfolgst du ein be-
stimmtes Ziel? Wenn du kein bestimmtes Datenaustauschformat brauchst, dann
kannst du es eigentlich beim zugegebenermaßen nicht sehr ökonomischen
Format von Excel belassen.
hth
ich würde es sehr gerne beim Format von Excel belassen aber ich bin momentan
am überlegen, ob ich eine
Schnittstelle zu einem anderen Programm (das leider diese gepackten und
binären Felder benötigt :(() realisiere.
Deshalb wollte ich erst mal die Möglichkeiten mit Excel/VBS abchecken.
Der Aufwand ist erstmal sekundär - hauptsache es geht überhaupt.
Gruß
Micha Donner
Matthias Tacke <Matt...@Tacke.de> schrieb in im Newsbeitrag:
8l2hav$s3p$14$1...@news.t-online.com...
Ohne *konkrete* Angaben kann dir da nicht weiter geholfen werden.
> > Schnittstelle zu einem anderen Programm (das leider diese gepackten und
> > binären Felder benötigt :(() realisiere.
> Dann fehlt abewr immer noch die Beschreibung wie dieses ominöse
^^^^^^^
> gepackte und binäre Feld aussehen soll. Oder in welcher Programmiersprache
> die Zielanwendung erstellt ist.
Na, eben gepackt, binär. Durchaus gängig bei "richtigen" Programmiersprachen.
Bsp:
dezimal ungepackt (Hex) gepackt (Hex)
(wie Text/EBCDIC) (Hälfte der Bytes gespart)
123 F1 F2 F3 12 3F
-123 F1 F2 D3 12 3D
Das kann man in XL mit Chr() oder Asci() z.B. irgendwie hinkriegen. Das
Problem ist dann das Abspeichern. Versuch doch, das ungepackte Format als Text
selber zusammenzubasteln und dann ne Packroutine zu schreiben. Problem:
Erzeugen eines Strings von (z.B.) 2 Byte mit dem Inhalt Hex: 12 3D. Könnte
aber funzen. Dann als Text abspeichern.
HTH
Piet
> > gepackte und binäre Feld aussehen soll. Oder in welcher
Programmiersprache
> > die Zielanwendung erstellt ist.
>
> Na, eben gepackt, binär. Durchaus gängig bei "richtigen"
Programmiersprachen.
>
> Bsp:
> dezimal ungepackt (Hex) gepackt (Hex)
> (wie Text/EBCDIC) (Hälfte der Bytes gespart)
> 123 F1 F2 F3 12 3F
> -123 F1 F2 D3 12 3D
>
Du gehst hier also von einem Signed Integer aus -> EBCDIC
Da gibt es aber noch mehr Float, Long, Double, Currency, BCD etc.
Und auf die Diskussion was eine richtige Programmiersprache ist, lass ich
mich
nicht ein: Es gibt sicherlich mehrere Richtige, unabhängig von persönlichen
Vorlieben.
Und der Fragesteller ließ das bisher im Dunkeln. Also war keine konkrete
Antwort möglich.
Matthias Tacke <Matt...@Tacke.de> schrieb in im Newsbeitrag:
8l4a2i$6g1$16$1...@news.t-online.com...
> Ominös laut Word Thesaurus [verdächtig|bedenklich|merkwürdig|undurchsichtig
> |anrüchig|unheilvoll|schlimme Vorbedeutung|usw.]
> zumindest ein paar der Synonyme passen doch ganz gut.
Ja, er hat einige Voraussetzungen nicht erwähnt. Die mögen bei jedem anders
vorbesetzt sein... -> ominös
> Du gehst hier also von einem Signed Integer aus -> EBCDIC
Bzw. FIXED DECIMAL, wie es in PL/1 heißt *kicher* vielleicht sagt man besser
"hieß"?
> Da gibt es aber noch mehr Float, Long, Double, Currency, BCD etc.
^^^ =
BinaryCodedDecimal?
Spricht man denn hier auch von "gepackten" Datenformaten? Bei allen Binaries
ist doch typischerweise Packen obsolet (Hallo Thesaurus ;-), denn die
Notwendigkeit besteht ja lediglich, um Speicherplatz zu sparen gegenüber
Dezimal ungepackt, oder (siehe Beispiel -123->F1F2D3->123D)?
Deshalb habe ich das so interpretiert.
> Und auf die Diskussion was eine richtige Programmiersprache ist, lass ich
> mich nicht ein
Da fehlte auch ein ;-). Wenn ich mir aber die Speicherungsoptionen von VBA
ansehe, die ja die Frage hier auslösen, finde ich das schon ziemlich arm.
> Und der Fragesteller ließ das bisher im Dunkeln. Also war keine konkrete
> Antwort möglich.
Hast ja Recht, aber vielleicht kommt er mit den Hinweisen ja etwas weiter.
Gruss,
Piet
was ich nicht ganz verstehe ist die Frage nach der
"Ziel"-Programmiersprache.
Aber falls es weiterhilft: es ist COBOL.
Und da gibt es eben nicht nur numerische, alphanumerische und Datumsfelder
sondern auch gepackte und binäre Felder.
Beispiele:
Gepackt:
Beispiel in Hexadezimaldarstellung dezimaler Werte in 3 Byte langen
gepackten Feldern.
Definition in COBOL: PIC S9(04)V9 COMP-3.
HOST EBCDIC und PC ASCII
Byte Nr: 1 2 3
HEX Inhalt: 00 01 2C = 1,2+ DEZIMAL
HEX Inhalt: 00 01 2D = 1,2- DEZIMAL
Binär:
Die physikalische Speicherung des Binärformates erfolgt rechtsbündig als
Dualzahl (d.h das niederwertigste Bit steht ganz rechts). Negative Zahlen
werden als Komplement dargestellt.
Beispiel in Hexadezimaldarstellung dezimaler Werte in 8 Byte langen
Binärfeldern.
Definition in COBOL: PIC S9(16)V99 COMP.
HOST EBCDIC und PC ASCII
Byte Nr: 1 2 3 4 5 6 7 8
HEX Inhalt: 00 00 00 00 00 00 00 00 = 0,00 DEZIMAL
HEX Inhalt: 00 00 00 00 00 00 00 01 = 0,01+ DEZIMAL
HEX Inhalt: FF FF FF FF FF FF FF FF = 0,01- DEZIMAL
HEX Inhalt: FF FF FF FF FF FF FF FE = 0,02- DEZIMAL
HEX Inhalt: 00 00 00 00 00 00 00 64 = 1,00+ DEZIMAL
HEX Inhalt: 00 00 00 00 00 01 86 A0 = 1.000,00+ DEZIMAL
HEX Inhalt: 00 00 00 00 00 12 BE F4 = 12.285,32+ DEZIMAL
HEX Inhalt: 00 00 00 01 FF FF FF FF = 85.899.345,91+ DEZIMAL
Gruß
Micha Donner
Piet Schmiedel <pi...@topmail.de> schrieb in im Newsbeitrag:
96401585...@news.thyssen.com...
Sub Zusammenfügen()
Dim Buffer1() As Byte, Buffer2() As Byte
'Erste zu lesende Datei
Open "c:\Quelldatei1" For Binary Access Read As #1
ReDim Buffer1(1 To LOF(1))
Get #1, , Buffer1
Close
'Zweite zu lesende Datei
Open "c:\Quelldatei2" For Binary Access Read As #1
ReDim Buffer2(1 To LOF(1))
Get #1, , Buffer2
Close
'Zusammengefügte Datei
Open "c:\DateiZusammen" For Binary As #1
Put #1, , Buffer1
Put #1, (UBound(Buffer1) + 1), Buffer2
Close
End Sub
Das Umsetzen der Datentypen in einzelne Bytes und umgekehrt
musst du schon selber erledigen. Die Api Funktion CopyMemory
sollte dir dabei helfen.
MfG
Michael
Ich glaub ich hab was gefunden:
Die Funktion zur Umwandlung einer Dezimalzahl in einen Binärstring prüft
einfach, ob die entsprechenden Bits gesetzt sind. Ist ein Bit gesetzt, wird
die "0" an der entsprechenden Stelle eines vorbereiteten Strings aus Nullen
in der Anzahl der maximalen Bit-Zahl gegen eine "1" ausgetauscht. Das
Verfahren ist erheblich schneller, als einen String von Position zu Position
aufzubauen und dabei jeweils eine "0" oder "1" davor zu hängen. Brauchen Sie
die eventuell führenden Nullen nicht, lassen Sie den optionalen Parameter
DoFormat weg. Die führenden Nullen werden dann gekappt. Setzen Sie ihn auf
True, erhalten Sie den vollen String.
Public Function DecBToBin(ByVal Value As Byte, _
Optional ByVal DoFormat As Boolean) As String
Dim i As Integer
Dim nBin As String
nBin = String$(8, "0")
For i = 0 To 7
If BitL(Value, i) Then
Mid$(nBin, 8 - i, 1) = "1"
End If
Next
If DoFormat Then
DecBToBin = nBin
Else
i = InStr(nBin, "1")
If i Then
DecBToBin = Mid$(nBin, i)
Else
DecBToBin = "0"
End If
End If
End Function
Soeine Funktion brüchte ich jetzt noch für gepackte Felder...
Gruß
Micha Donner
Michael Schwimmer <Schw...@t-online.de> schrieb in im Newsbeitrag:
8l4f39$q1o$15$1...@news.t-online.com...
> Hallo Matthias, hallo Piet,
>
> was ich nicht ganz verstehe ist die Frage nach der
> "Ziel"-Programmiersprache.
> Aber falls es weiterhilft: es ist COBOL.
> Und da gibt es eben nicht nur numerische, alphanumerische und Datumsfelder
> sondern auch gepackte und binäre Felder.
>
Hallo Michael,
wir sind mit diesem Beitrag in der 10. Stufe dieses Thread angekommen,
und erst jetzt gibst du einige weiterhelfende Details deines Problems
weiter. Scheinbar kannst du dir nicht vorstellen wie viele Datei- und
Zahlenformate bzw. Programmiersprachen es gibt. Ausgerechnet Cobol ge-
hört nicht zu meinen Stärken. Das von dir beschriebene 8 Byte Format
scheint mir ein einfaches Integerformat mit 2 implizierten Nachkomma-
stellen zu sein. (Mit dem drohenden Euro haperts dann aber.)
Vom Aufbau entspricht das VB-Currency am ehesten diesem Format:
die VB-Hilfe sagt:
*******************
Currency-Datentyp
Variablen vom Datentyp Currency werden als 64-Bit-Zahlen (8 Bytes)
in einem ganzzahligen Format gespeichert und durch 10.000 dividiert,
was eine Festkommazahl mit 15 Vorkomma- und 4 Nachkommastellen ergibt.
Diese Darstellung ergibt einen Wertebereich von
-922.337.203.685.477,5808 bis 922.337.203.685.477,5807.
Das Typkennzeichen für Currency ist das Zeichen (@).
Der Datentyp Currency eignet sich besonders für Berechnungen mit
Geldbeträgen und für Festkommaberechnungen, die eine hohe Genauigkeit
erfordern.
*****************
Bis auf die Verschiebung um 2 Nachkommastellen deckt sich das doch.
Und das kann man ja relativ leicht nachbauen. Wenn das Komplement
in gleicher Weise gebildet wird könnte das ja klappen.
Bleibt die Frage nach dem Datei-Format. Gibts es irgendwelche Header?
Wenn Ja wie ist er aufgebaut?
Wieviele Felder sind in einem Satz/Record? Gibt es einen Satztrenner?
Kann man das alles in VB einfach abbilden? Wahrscheinlich.
Ein erster Versuch:
Die genannten Beispielzahlen stehen in einer Exceltabelle in A1:A8
Der folgende Abschnitt in ein Modul des Arbeitsblattes
************Schnipp************
Type Datensatz ' Datentyp definieren.
Betrag As Currency
End Type
Sub TestConvert()
Dim DSatz1 As Datensatz ' Variable deklarieren.
Dim Wert As Currency
Sheets("Tabelle1").Select
Range("A1").Select
' Datei mit wahlfreiem Zugriff öffnen.
Open "D:\DATEI1" For Random As #1 Len = Len(DSatz1)
' Schleifendurchläufe.
For DSatzNummer = 1 To 8
' Daten aus Tabelle holen
Wert = Cells(DSatzNummer, 1) / 100
' und zur Kontrolle anzeigen
Debug.Print DSatzNummer; " = "; Wert
DSatz1.Betrag = Wert
' Datensatz in Datei schreiben.
Put #1, DSatzNummer * 2 - 1, DSatz1
' Zweimal damit der Debugauszug passt
Put #1, DSatzNummer * 2, DSatz1
Next DSatzNummer
Close #1
End Sub
************Schnipp************
Und das ausführen von TestConvert erzeugt diese Datei:
D:\>dump datei1
DUMP - HEX/ASCII-Dump von Dateien Ver. 1.0
DUMP-Datei: D:DATEI1.
0000: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00
0010: 01 00 00 00 00 00 00 00 - 01 00 00 00 00 00 00 00
0020: FF FF FF FF FF FF FF FF - FF FF FF FF FF FF FF FF
0030: FE FF FF FF FF FF FF FF - FE FF FF FF FF FF FF FF
0040: 64 00 00 00 00 00 00 00 - 64 00 00 00 00 00 00 00
0050: A0 86 01 00 00 00 00 00 - A0 86 01 00 00 00 00 00
0060: F4 BE 12 00 00 00 00 00 - F4 BE 12 00 00 00 00 00
0070: FF FF FF FF 01 00 00 00 - FF FF FF FF 01 00 00 00
Dump beendet.
Und das Ergebnis zeigt das Intel's Entscheidung zwischen Big und
Small Endianformat beim Prozessordesign zu unseren Ungunsten
ausgegangen ist.
Aber das lässt sich auch noch beheben. Muus aber nicht jetzt sein.
hth
Wie erwartet, ist die Datei jetzt 26 Byte groß.
Currency =8 Byte
Integer =2 Byte
Long =4 Byte
Single =4 Byte
Double =8 Byte
Wenn du eine Variable in ein Byte Array umwandeln willst,
hilft dir, wie gesagt, CopyMemory.
Hier ein Beispiel, das Currency in ein 8 Byte Datenfeld
umwandelt und zurück.
Private Declare Sub CopyMemory Lib "kernel32" Alias _
"RtlMoveMemory" (Destination As Any, Source As Any, _
ByVal Length As Long)
Sub CurInByteInCur()
Dim a As Currency, b(1 To 8) As Byte
a = 123456789012345.1234@
CopyMemory b(1), a, 8
a = 0
CopyMemory a, b(1), 8
MsgBox a
End Sub
Aber wie gesagt, ich habe immer noch keine Ahnung, was
du erreichen willst.
MfG
Michael
o.k. - nochmal von vorn.
Mein Ziel ist:
Die Ausgabe von Werten in Feldern aus einem Excel-Sheet in eine binäre
Datei.
Es handelt sich hier um "normale" Felder wie number, character und date
sowie um "ominöse" Felder wie gepackt und binär.
Beispiele zu "gepackt" und "binär" siehe oben.
Ich will also nichts aus einer Datei auslesen sondern in eine Datei
schreiben.
Gruß
Michael Donner
Michael Schwimmer <Schw...@t-online.de> schrieb in im Newsbeitrag:
8l54m2$4at$15$1...@news.t-online.com...
Hallo Michael
> o.k. - nochmal von vorn.
> Mein Ziel ist:
> Die Ausgabe von Werten in Feldern aus einem Excel-Sheet in eine binäre
> Datei.
> Es handelt sich hier um "normale" Felder wie number, character und date
Dim a as double ' single, integer, long, currency, date, string
a=cdbl(sheets(1).Range("A1").value) 'csng, cint, clng, ccur, cdate, cstr
Open "c:\PUTGET.txt" For Binary As #1
Put #1,PositionInDatei , a
Close
> sowie um "ominöse" Felder wie gepackt und binär.
> Beispiele zu "gepackt" und "binär" siehe oben.
Mit dem Format "gepackt" kann ich nichts anfangen. Aus nur zwei
Beispielen kann ich kein Schema erkennen.
Binär ist Currency mit zwei Nachkommastellen.
Dim a As Currency, BinärTypArrayLoVorne(1 To 8) As Byte
Dim c As Integer, BinärTypArrayLoHinten(1 To 8) As Byte
Dim StringvariableZumSpeichern As String * 8
With Sheets(1)
a = .Cells(1, 1)'Zahl in Range A1
c = InStr(1, CStr(a), ",")
If c > 0 Then
a = CCur(Left$(CStr(a), c + 2))
End If
a = a / 100
CopyMemory BinärTypArrayLoVorne(1), a, 8
'Jetzt ist im Array BinärTypArrayLoVorne dein
'Typ Binär, aber Lo-Byte vorn
For c = 1 To 8
BinärTypArrayLoHinten(9 - c) = _
BinärTypArrayLoVorne(c)
Next
'Jetzt ist im Array BinärTypArrayLoHinten dein
'Typ Binär, das Lo-Byte hinten
CopyMemory ByVal StringvariableZumSpeichern, _
BinärTypArrayLoHinten(1), 8
'Jetzt ist in StringvariableZumSpeichern dein
'Typ Binär, das Lo-Byte hinten
> Ich will also nichts aus einer Datei auslesen sondern in eine Datei
> schreiben.
Open For Binary, Put, Close. Siehe Online-Hilfe.
MfG
Michael
> Mit dem Format "gepackt" kann ich nichts anfangen. Aus nur zwei
> Beispielen kann ich kein Schema erkennen.
I.A. meint gepackt: 1 Ziffer pro Halbbyte (EBCDIC-gecodeter Ziffernteil),
Vorzeichen im letzten Halbbyte, F = +, D = -.
Also Dec. 123 -> EBCDIC Text F1 F2 F3 (3 byte) -> EBCDIC ungepackt Hex. F1
F2 F3 (3 byte) -> EBCDIC gepackt Hex. 12 3F (2 byte).
Dec. -123 -> EBCDIC Text 60 F1 F2 F3 (4 byte) -> EBCDIC ungepackt Hex. F1
F2 D3 (3 byte) -> EBCDIC gepackt Hex. 12 3D (2 byte).
Nachkommastellen gem. Variablendefinition, wird also beim Read festgelegt.
HTH
Piet
Gepackt meinte in diesem Fall die Cobol Comp-Formate. Ich kann mich noch
dunkel an meine ersten Programmierschritte mit Cobol erinnern. Leider habe
ich keine Unterlagen mehr über den Aufbau der Comp-Formate. Vielleicht gibt
es aber auf irgendeiner Internet-Site noch ein paar historische Dokus.
Jörg
Gruß
Micha Donner
Sub InPackedEineNachkommastelle()
Dim PackedTypArray(1 To 3) As Byte, a, c
Dim Vorzeichen As String
Dim StringvariableZumSpeichern As String * 3
With Sheets(1)
a = .Cells(3, 1)
If Abs(a) > 9999.9 Then MsgBox "Zahl zu groß": Exit Sub
If a < 0 Then
Vorzeichen = "F"
Else
Vorzeichen = "D"
End If
a = Abs(a)
c = InStr(1, CStr(a), ",")
If c > 0 Then
a = Left$(CStr(a), c + 1)
End If
a = Format$(a * 10, "00000")
PackedTypArray(1) = CByte("&H" & Hex$(Mid$(a, 1, 1)) & Hex$(Mid$(a, 2, 1)))
PackedTypArray(2) = CByte("&H" & Hex$(Mid$(a, 3, 1)) & Hex$(Mid$(a, 4, 1)))
PackedTypArray(3) = CByte("&H" & Hex$(Mid$(a, 5, 1)) & Vorzeichen)
CopyMemory ByVal StringvariableZumSpeichern, PackedTypArray(1), 3
End With
End Sub
MfG
Michael