Neuigkeiten:

Wenn ihr euch für eine gute Antwort bedanken möchtet, im entsprechenden Posting einfach den Knopf "sag Danke" drücken!

Mobiles Hauptmenü

Teile einer CSV Datei in Access Formular einfügen

Begonnen von Sproket_1972, Juni 30, 2016, 18:06:37

⏪ vorheriges - nächstes ⏩

Sproket_1972

Hallo zusammen,
ich versuche eine CSV Datei in meine Access Formular zu importieren.
Das habe ich über "DoCmd.TransferText acLinkDelim, ImportSpez, TmpLink, AktDatFullNam" ausgeführt.
Klapp auch prima !!!

Jetzt das Problem.
Die CSV Datei ist mehr als 255 Spalten lang, genau 457 Spalten.
Ich suche eine Möglichkeit nur einzelne Felder aus der CSV Datei in mein Formular zu übertragen.

Help me please :)

Beaker s.a.

Hallo,
Du kannst doch mit dem Importassistenten genau auswählen welche
Spalten du importieren willst.
Oder werden da gar nicht erst alle Spalten der .csv angezeigt?
gruss ekkehard
Alles, was geschieht, geschieht. - Alles, was während seines Geschehens etwas anderes geschehen lässt, lässt etwas anderes geschehen. - Alles, was sich selbst im Zuge seines Geschehens erneut geschehen lässt, geschieht erneut. - Allerdings tut es das nicht unbedingt in chronologischer Reihenfolge.
(Douglas Adams, Mostly Harmless)

Sproket_1972

Hallo Moin,
es werden genau 255 angezeigt.
Es sind aber mehr Spalten.
Habe die Spalten 1-100 ausgewählt in der Import_Spec.
Die werden dann auch übertragen.
Wenn ich aber die 101-255 auswähle werden mir die Spalten 1-100 übertragen ?
Gibt es da einen Kniff ?
siehe ImportSec !

Lachtaube

Nun, die PDF-Datei wird kaum zu einer Lösung verhelfen. Mit einem Auszug der CSV-Daten (ggf. sensible Felder anonym gestalten) und einer kurzen Erläuterung zu den Feldern ist die Aussicht auf Hilfe vermutlich größer.
Grüße von der (⌒▽⌒)

Beaker s.a.

Hallo,
ZitatDas habe ich über "DoCmd.TransferText acLinkDelim, ImportSpez, TmpLink, AktDatFullNam" ausgeführt.
Klapp auch prima !!!
Heisst das denn, dass du alle Felder importieren konntest, oder eben
nur die ersten 100.
Da bleibt dir nichts anderes übrig als die .csv vorher aufzuteilen bzw.
den Export so einzurichten das da schon weniger Spalten rauskommen.

ZitatWenn ich aber die 101-255 auswähle werden mir die Spalten 1-100 übertragen ?
Dazu kann ich nichts sagen, mit so vielen Spalten arbeite(t) ich (man) in Datenbanken nicht.

Leider hast du auch den Sinn verschwiegen. Ich denke da muss zuerst
ein brauchbares Datenmodell in Access erstellt werden.

gruss ekkehard
Alles, was geschieht, geschieht. - Alles, was während seines Geschehens etwas anderes geschehen lässt, lässt etwas anderes geschehen. - Alles, was sich selbst im Zuge seines Geschehens erneut geschehen lässt, geschieht erneut. - Allerdings tut es das nicht unbedingt in chronologischer Reihenfolge.
(Douglas Adams, Mostly Harmless)

Sproket_1972

Hallo,
das ist richtig !
Danke nochmal für die Antwort.
Also habe die CSV als XLS angehängt weil '.csv nicht anzuhängen ist ??
Die Felder sind alle als Text zu behandeln.
Wollte wegen der Größe der CSV die Felder auf mehrere Formulare aufteilen.
Klappt auch alles  wunderbar aber leider nur bis zum Feld 255.

Habe den Code zum importieren angehängt.
Mit diesen Code hole ich mir die CSV in das Formular hinein.



"
Private Sub Importieren_Click()
'geteset AC97, AC2000
' es werden mehrere GLEICHARTIGE Importdateien nacheinander verknüpft und an
' eine Haupttabelle angefügt
' Voraussetzungen :
' TXT,CSV : Importspezifikation wurde erstellt und gespeichert
     ' Startverzeichnis für die Suche angeben
     
     ' einen Filetyp bzw Dateinamensbild freischalten
     ' ("*.txt";"*.csv";"2005*.xls")
     
     ' Zieltabelle, an welche die Daten angefügt werden sollen
     Const ZielTab = "Zaehlerstaende"
     Dim i As Integer
     Dim AktDatei As String
     Dim TxtDatum As String
     
     
     
     'Datum in Text umwandeln
     Debug.Print TxtDatum
     Datum = Str(Date)
     Debug.Print Datum
     Datum = Format(Date, "yyyymmdd")  ' heutiges Datum als Text z.B.: 20160622
     Debug.Print Datum
     DatTyp = ("Test*" & Datum & ".csv")
     'Const DatTyp = "Test*.csv"
     Const SuchVerzeichnis = "I:\ORG\OPOTSS\Dispatching\Zaehlerstaende_Epe\"
     AktDatei = Dir(SuchVerzeichnis & "\" & DatTyp)
     While Len(AktDatei) > 0
          Debug.Print AktDatei
          ' Nächste Zeile startet Import für eine Textdatei (CSV,TXT)
          EineTXTDateiEinlinkenUndAnfügen SuchVerzeichnis & "\" & AktDatei, _
                                         ZielTab
          ' Nächste Zeile startet Import für eine Exceldatei (XLS)
          'EineExcelDateiEinlinkenUndAnfügen SuchVerzeichnis & "\" & _
          '                                  AktDatei, ZielTab
          ' Nächste Zeile startet Import für eine Exceldatei (XLS) mit allen
          ' Tabellen
          'EineExcelDateiMitAllenTabellenEinlinkenUndAnfügen SuchVerzeichnis & _
          '                                                  "\" & AktDatei, _
          '                                                  ZielTab
          AktDatei = Dir ' nächste Datei
     Wend
End Sub

Sub EineTXTDateiEinlinkenUndAnfügen(AktDatFullNam As String, _
                                     ZielTab As String)
' eigentliche Import/Verknüfungsfunktion
     Const TmpLink = "TabtmpLink"     ' beliebiger Tabellenname (wird gelöscht)
     Const ImportSpez = "Allgemein_Import"  ' Name deiner Importspezifikation
   
     ' CSV einlinken
     On Error Resume Next
     DoCmd.DeleteObject acTable, TmpLink
     On Error GoTo 0
     'oCmd.TransferText acImportDelim, "Allgemein_Import", TableName:="Zaehler3 ", FileName:=filePath, HasFieldNames:=True
     DoCmd.TransferText acLinkDelim, ImportSpez, TmpLink, AktDatFullNam
     ' Anfügen
     CurrentDb.Execute "INSERT INTO " & ZielTab & _
                           " SELECT " & TmpLink & ".* " & _
                              "FROM " & TmpLink & ";"
End Sub
"

Sproket_1972

Hier nochmal die Test Datei als ZIP.
die *.Xls ist ja nur 255 Spalten breit :)

Sproket_1972

Zitat von: Beaker s.a. am Juni 30, 2016, 21:21:13
Hallo,
ZitatDas habe ich über "DoCmd.TransferText acLinkDelim, ImportSpez, TmpLink, AktDatFullNam" ausgeführt.
Klapp auch prima !!!
Heisst das denn, dass du alle Felder importieren konntest, oder eben
nur die ersten 100.
Da bleibt dir nichts anderes übrig als die .csv vorher aufzuteilen bzw.
den Export so einzurichten das da schon weniger Spalten rauskommen.

ZitatWenn ich aber die 101-255 auswähle werden mir die Spalten 1-100 übertragen ?
Dazu kann ich nichts sagen, mit so vielen Spalten arbeite(t) ich (man) in Datenbanken nicht.

Leider hast du auch den Sinn verschwiegen. Ich denke da muss zuerst
ein brauchbares Datenmodell in Access erstellt werden.

gruss ekkehard

Die CSV bekomme ich per Mail und ist immer gleich aufgebaut.
Ja genau dass möchte ich ja gerne erfahren !!??
Wie kann ich den Export so einrichten das man z.Bsp. nur 120 ausgesucht Felder importiert.

Immer noch Danke für die Vorschläge.

Lachtaube

Hi,

die gezeigten Daten lassen leider ein sinnvolles Modellieren für einen Nicht-Esoteriker nicht zu.

CSV-Dateien lassen sich mit der Open-Anweisung öffnen. Nach dem Öffnen kann man Zeile für Zeile der Datei einlesen (Line Input # Statement). Eine Zeile könnte man in ein Datenfeld (Array) aufsplitten (Split Function) und die gewünschten Inhalte (über entsprechende Recordset(s) oder auch Anfügeabfrage(n)) in einen oder mehrere neue Datensätze schreiben. Am Ende schließt man die Datei wieder (Close Statement).

Dieses Verfahren wird in Programmiersprachen allgemein als Parsen bezeichnet.
Grüße von der (⌒▽⌒)

Beaker s.a.

Hallo,
Ich sehe da nur zwei Möglichkeiten; - jede bessere Lösung ist willkommen.
1. Die ankommende .csv in Ecxel öffnen und auf zwei Tabelle aufteilen und
getrennt wieder als .csv abspeichern. Dann würde ich diese beiden Dateien 
auch nicht in Access importieren sondern verknüpfen. Dann kannst du per
Abfrage(n) auf einzelne Felder zugreifen.
2. Import per benutzerdefiniertem Datentyp. Da weiss ich aber nicht, ob man
da nicht auch auf 255 Variablen(Felder) beschränkt ist. Bei dieser Methode
hast du auch die Möglichkeit direkt in mehrere Tabellen zu schreiben.
Prinzip (Luftcode):
Private Type ImportDS
    FELD1   As String
    FELD2   As String
    FELD3   As String
    FELD4   As String
    FELD5   As String
.
.
    FELD457   As String
End Type

Private Sub fImport()
    Dim intDateiNr       As Integer        'erste freie Dateinummer
    Dim strImpDatPfad    As String        'Pfad der Import-Datei
    Dim intDateiNr       As Integer        'erste freie Dateinummer
    Dim impRec     As ImportDS        'Datensatz wie oben beschrieben
    Dim rst           As DAO.Recordset

'    strImpDatPfad = musst du irgendwo herholen

    intDateiNr = FreeFile
    Open strImpDatPfad For Binary As #intDateiNr Len = Len(impRec)
    Get #intDateiNr, , impRec

    'RS öffnen
    Set rst = CurrentDb.OpenRecordset(Name:="EineTabelle")

    Do Until #intDateiNr.EOF   '<- bei diesem Ausdruck bin ich nicht sicher
       rst.AddNew
           rst.Fields("Feldname1") = impRec.FELD1
           rst.Fields("Feldname2") = ImpRec.FELD2
       rst.Update

        Get #intDateiNr, , impRec

    Loop

    Close #intDateiNr
    rst.Close
    Set rst = Nothing

End Sub


hth
gruss ekkehard
Alles, was geschieht, geschieht. - Alles, was während seines Geschehens etwas anderes geschehen lässt, lässt etwas anderes geschehen. - Alles, was sich selbst im Zuge seines Geschehens erneut geschehen lässt, geschieht erneut. - Allerdings tut es das nicht unbedingt in chronologischer Reihenfolge.
(Douglas Adams, Mostly Harmless)

crystal

Hallo,
zunächst Mal würde ich natürlich das "Design" der CSV-Dateien überdenken. Vllt. kannst du an der Quelle die Excel-Datei so ändern, dass sie von vornherein 2 Files erstellt...

Ansonsten:
Wenn Access die Import-Definition auf 255 Spalten beschränkt (durchaus nachvollziehbar), dann musst du eben deine eigenen Import-Definitionen definieren, etwa so:
Variante 1:
1. erstelle eine Tabelle ImpDefs mit 457 Datenfeldern (oh Graus!) als Textfelder und 457 Ja/Nein-Feldern sowie beschreibenden Textfeldern (angelegt von, Verwendung, CSV-Dateinamens-Muster...).
2. erstelle ein Formular mit 457 Textfeldern (schmal und lang für die Darstellung der Kopfzeile(n)) und 457 Checkboxen. 23 Felder nebeneinander und das 20mal untereinander. (VBA!)
3. lade per VBA die ersten Zeilen der CSV und splitte die Felder jeder Zeile. Kopiere den Split-Vektor nach jeder gelesenen Zeile in ein 2-dimensionales Array. Bau dann aus den gelesenenen Zeilen 457 aussagekräftige Textfelder zusammen, Zeilen-Umbruch jeweils mit VBCRLF, etwa so
for i= 1  to 457
for j= 1 to 5  'Bsp: erste 5 Zeilen werden eingelesen (Spaltennamen)
  textfeld(i) = textfeld(i) & arrayfeld(i,j) & vbcrlf
next
next
4. schreibe diese 457 Textfelder nun in die 457 Textfelder des Formulars.
5. mit den 457 Checkboxen kannst du dann angeben, welche Felder du importieren möchtest.
6. diesen Mammut-Datensatz kannst du dann für spätere bzw. wiederkehrende Verwendung speichern.

Variante 2:
1. Tabelle ImpDefs mit ein paar beschreibenden Textfeldern.
1a. Tabelle ImpDefItems mit Referenz auf ImpDefs, einem Text- und einem Ja/Nein-Feld.
2. erstelle ein Unterformular (UFO) für ImpDefItems bestehend aus einem mehrzeiligen Textfeld und darunter einer Checkbox.
2a. erstelle ein Formuar für ImpDefs, in das du das obige Ufo platzierst und so klein wie möglich/gewünscht machst.
2b. kopiere das UFO per VBA 456mal (Link-Felder nicht vegessen)...
3. bis 6. ähnlich wie oben.

Variante 3:
1. öffne eine CSV-Datei als Muster in Excel.
2. füge eine neue 1. Zeile ein, setze in jedes Feld der Zeile ein Kontrollkästchen.
3. speichere die Datei als Muster-CSV.

Kurze Diskussion der Varianten:
v1 - grauenhaft, Mammut-Tabelle mit knapp 1000 Feldern!
v2 - besser, da normalisiert - kleine, schmale Tabellen
v1 - immenser Definitions-Aufwand (Tabellenfelder, Formularfelder)
v2 - minimaler Definitions-Aufwand, aber VBA-Code zum Kopieren der UFOs nötig
v1 - kratzt an der Access-Grenze von ca. 920 (?) Feldern pro Formular
v3 - ohne ACCESS-Klimmzüge
v3 - Namenskonvention für Muster erforderlich (als Access-Tabelle...)
v3 - geringster Aufwand
v3 - hier könnte man in einer weiteren Zeile auch noch das Ziel-Feld in der Access-Tabelle unterbringen...


Egal, welche Variante du bauen solltest - der Programm-Ablauf für den eigentlichen Daten-Import wäre dann:
1. Import-Definition laden.
2. CSV-Datei zeilenweise lesen, dabei Kopfdaten überspringen und die gewünschten Felder speichern (Zeile in Vektor splitten etc.).

Übrigens: die Variante 2 von Ekkehard halte ich für etwas zu aufwändig, da ein solcher Datentyp mit 457 einzelnen Strings im Prinzip auch nichts anderes ist als ein String-Vektor (dim MyString(457) as string).
Wenn man eine Zeile der CSV-Datei einliest, kann man sie mit SPLIT leicht in einen  solchen Vektor überführen und über dessen Elemente loopen (starten bei 0).

Und noch ein Übrigens: in der Beispiel-xls sind viele Spalten nicht belegt, irgendwo steht ein einsames "c". Wäre es evtl. denkbar, die CSV-Dateien per Excel-VBA umzukopieren (nur Spalten, in denen Werte stehen)? Könnte dadurch das 255-Maximum nicht unterschritten werden, um dann wieder die Access-Import-Definition nutzen zu können?

Vielen Dank jedenfalls für alle, die diese lange Antwort lesen.

Grüße,

c


Wer Fehler in meinen Antworten findet, darf sie behalten, muss sie aber kommentieren. ;-)
Dies ist keineswegs arrogant gemeint, sondern soll nur unterstreichen, dass meine Antworten - natürlich - nicht immer fehlerfrei sind und sein können.
Devise: bitte immer erst selbst probieren!

Aus gesundheitlichen Gründen nur noch selten dabei...

MaggieMay

#11
Hi,
Zitat von: crystal am Juli 01, 2016, 11:05:57
Wenn Access die Import-Definition auf 255 Spalten beschränkt
es geht hier nicht um eine Import-Definition sondern um die maximale Anzahl von Datenfeldern in einer Tabelle. Variante-1 ist demnach gar nicht erst umsetzbar.

Die Lösung wird vmtl. darin bestehen, die csv-Datei als Textdatei zeilenweise einzulesen und innerhalb von Access aufzusplitten.

PS:
Wenn es sich allerdings um eine Excel-Tabelle handelt, so kannst du beim Verknüpfen oder Einlesen mit der TransferSpreadsheet-Methode auch einen Bereich angeben, bspw. "A:EZ" und "FA:MN".
Freundliche Grüße
MaggieMay

Beaker s.a.

Hallo crystal,
ZitatÜbrigens: die Variante 2 von Ekkehard halte ich für etwas zu aufwändig, da ein solcher Datentyp mit 457 einzelnen Strings im Prinzip auch nichts anderes ist als ein String-Vektor (dim MyString(457) as string).
Wenn man eine Zeile der CSV-Datei einliest, kann man sie mit SPLIT leicht in einen  solchen Vektor überführen und über dessen Elemente loopen (starten bei 0).
Was da jetzt aufwändiger ist, lass ich andere beurteilen.
Da mir aber auch nicht klar ist ob da jetzt im Höchstfall eine Auswahl von
255 Feldern in eine Tabelle importiert werden soll, oder alle 457 Felder
in mehrere Tabellen, und wie da die Reihenfolge der Felder angelegt ist,
finde ich es so, mit "Feldnamen", einfacher diese Tabellen zu beschreiben,
als irgendwelche Verrenkungen mit abzählen zu veranstalten; - ich muss
mir einfach keine Gedanken um eine Reihenfolge zu machen.

Ich hätte aber noch eine Frage in die Runde zu meinem Code bzügl. der
Loop-Bedingung (habe das ja nicht gestestet). Hat #intDateiNr überhaupt
eine Eigenschaft EOF?
Den Code hatte ich aus einer 15 Jahre alten Prozedur zusammen gestoppelt,
wo es aber um den Import einer Textdatei mit fester DS- und Feldlänge geht.
Zudem haben die DS dort eine Kennung, an der ich die Loop-Bedingung
festmachen konnte.
Das Do Until #intDateiNr.EOF war also nur geraten.
Würde mich also interessieren, wie's richtig wäre.

gruss ekkehard
Alles, was geschieht, geschieht. - Alles, was während seines Geschehens etwas anderes geschehen lässt, lässt etwas anderes geschehen. - Alles, was sich selbst im Zuge seines Geschehens erneut geschehen lässt, geschieht erneut. - Allerdings tut es das nicht unbedingt in chronologischer Reihenfolge.
(Douglas Adams, Mostly Harmless)

DF6GL

Hallo,


ZitatHat #intDateiNr überhaupt
eine Eigenschaft EOF?


Nein, es handelt sich bzgl. von Datei-Operationen um eine Funktion.

aus der VBA-Hilfe:


ZitatDim InputData
Open "MYFILE" For Input As #1    ' Open file for input.
Do While Not EOF(1)    ' Check for end of file.
    Line Input #1, InputData    ' Read line of data.
    Debug.Print InputData    ' Print to the Immediate window.
Loop
Close #1    ' Close file.

Beaker s.a.

Danke Franz,
Das hatte ich nicht gefunden. Unter welchem Begriff steht das dort?
Ich glaube, ich hatte unter "Open" geschaut. Bin da aber auch mit
Querverweisen nicht drauf gekommen.
Aber ganz verkehrt war die Idee ja nicht, nur falsche Syntax; - Korrektur:
Do Until EOF(intDateiNr)

Und, deine Einschätzung der Vorschläge?

gruss ekkehard
Alles, was geschieht, geschieht. - Alles, was während seines Geschehens etwas anderes geschehen lässt, lässt etwas anderes geschehen. - Alles, was sich selbst im Zuge seines Geschehens erneut geschehen lässt, geschieht erneut. - Allerdings tut es das nicht unbedingt in chronologischer Reihenfolge.
(Douglas Adams, Mostly Harmless)