23. september 2014 - 21:43Der er
12 kommentarer og 1 løsning
Import af udvalgte linier i CSV fil
Hejsa
Jeg er kommet i besiddelse af en ret stor csv-fil, der indeholder data indeholdende dokumentations relationer. I den sammenhæng skal jeg kunne trække linier ud af csv filen ved at søge efter en del af linien som jeg har opgivet på forhånd.
Problemet for mig består i at csv-filen som sagt er rigitg stor, ca 1.200.000 linier. Dette betyder også at den er for stor til et ark i excel, som jeg arbejder i.
Jeg kunne godt tænke mig at vide hvordan jeg skal gribe det an at få de udvalgte linier ud af csv filen. Som jeg ser det er der kun et par muligheder.
Jeg kan åbne csv filen i notepad og dele den ud over 2 eller flere excel ark og derved søge dem igennem ved hjælp af vba script. Dog tænker jeg at denne metode er meget langsom, rent processerings mæssigt.
Alternativt kunne man vel lave en database indeholdende csv filen og derved søge i denne. Jeg har desværre ingen erfaring i at lave databaser. Men vil bestemt være lydhør hvis der er en der kan pege mig i den rigtige retning for at kunne lave sådan en selv.
Jeg håber der er en der kan hjælpe mig da jeg er en smule i tidsnød.
Følgende der både er vb, vba og vbs udvælger hvor både 'kolonne B' er "Kurt" og 'kolonne C' er "Hansen". Opdelingen i kolonner til brug for udvælgelse er baseret på funktionen split - denne vil fejle hvis ';' tegnet er indeholdt i gåseøjne omsluttet value.
Dim line, lineArr, outlines Const inpFileN = "C:\mappe\storfil.csv" Const outFileN = "C:\mappe\lillefil.csv" With CreateObject("Scripting.FileSystemObject").OpenTextFile(inpFileN, 1) While Not .AtEndOfStream line = .ReadLine lineArr = split(line, ";") If lineArr(1) = "Kurt" and lineArr(2)="Hansen" Then outlines = outlines & line & vbCrLf Wend .Close End With With CreateObject("Scripting.FileSystemObject").CreateTextFile(outFileN, True) .Write (outlines) .Close End With
Det ser interressant ud det du har lavet der. Jeg har en kolonne med, lad os sige navne, som skal søges efter i csv-filen. Så der kan godt være 700 forskellige navne som skal søges efter i csv-filen. Og i csv-filen vil det enkelte navn være nævnt på flere linier. Det er alle disse linier jeg er interresseret i. Da det gerne skulle mindske størrelsen af den tabel jeg skal bruge fra 1.200.000 linier til 5.000 linier.
Så jeg skal bruge en "For Next" funktion til at søge alle navne op i csv-filen, tror jeg?
Hvordan adskiller linier med navne sig fra de linier som ikke skal med? eller på en anden måde: Er det en liste af udvalgte navne som skal medtages og på hvilken form har du disse navne?
Alle linier er bygget således op: Document Name ; Document Desription ; Class ; File Path ; Target Name
Hvor jeg har en liste med Target Name som skal søges op i csv-filen og hvert "hit" skal kopiere hele linien til et seperat sheet, eller csv fil i dette tilfælde er helt fint.
Alt data er en blanding af tal og bogstaver, så string vil være deres form tænker jeg.
With CreateObject("Scripting.FileSystemObject").OpenTextFile(tNameFile, 1) While Not .AtEndOfStream tnDic.Add .ReadLine, "": Wend: End With
With CreateObject("Scripting.FileSystemObject").OpenTextFile(inpFileN, 1) While Not .AtEndOfStream line = .ReadLine lineArr = Split(line, ";") If tnDic.Exists(Replace(lineArr(csvColCmp), """", "")) Then outlines = outlines & line & vbCrLf Wend .Close End With With CreateObject("Scripting.FileSystemObject").CreateTextFile(outFileN, True) .Write (outlines) .Close End With Set tnDic = Nothing
Men der kan være den nævnte usikkerhed med kolonne identifikation - og så må taget Names i csv filen ikke indeholde gåseøjne (men gerne være omsluttet deraf) - for så skal der tages mere hånd om det end vist. Terry's løsning med import til database er mere sikker (to tabeller)
Terry's løsning ville jeg også rigtig gerne. og kan også få min csv-fil ind i en access database, men hvordan jeg får hentet dataen derfra og ind i mit excel ark har jeg ikke kunne hitte ud af.
Der er røget et semikolon ind - linie 5 skal være const csvColCmp=4 ' 5 kolonne i csv fil. Det er ligemeget med headeres Sikkert OK med diverse tegn i taget names - prøv at teste med 40-50 linier i csv fil og vurder.
Det fungere super godt i mine små tests, så tak for det. Men når jeg skal køre hele filen, alle 1.200.000 linier så får jeg en fejl efter noget tid: Script: csv test.vbs Line: 17 Char: 9 Error: Subscript out of range: '[number:4]' code: 800A0009 Source: Microsoft VBScript runtime error
Her er tilsat lidt - bemærk linien 'Const showErrorLinesNr = False' - hvis den ændres til true kommer der en meddelelsesboks med linienummer på linien der ikke har mindst csvColCmp semikoloner.
With CreateObject("Scripting.FileSystemObject").OpenTextFile(tNameFile, 1) While Not .AtEndOfStream tnDic.Add .ReadLine, "": Wend: End With
With CreateObject("Scripting.FileSystemObject").OpenTextFile(inpFileN, 1) While Not .AtEndOfStream line = .ReadLine lineArr = Split(line, ";") lineNr = lineNr + 1 If UBound(lineArr) >= csvColCmp Then If tnDic.Exists(Replace(lineArr(csvColCmp), """", "")) Then outlines = outlines & line & vbCrLf ElseIf showErrorLinesNr Then MsgBox "error in line: " & lineNr End If Wend .Close End With With CreateObject("Scripting.FileSystemObject").CreateTextFile(outFileN, True) .Write (outlines) .Close End With Set tnDic = Nothing
Den egentlige belønning er slet ikke point, men det at kunne skrive noget der selv beviser sit værd - det var godt du kunne bruge det. Tænkte faktisk på en lille forbedring: Antag, at der blandt de 1.200.000 linier er 1000 linier som 'fejler' - men at man ønsker at se disse linier for at chekke deres indhold. Der duer en meddelelsesboks ikke - men med følgende ændring tror jeg det er muligt
A. linien: MsgBox "error in line: " & lineNr ændres til Wscript.Echo line B. 6' linien skal være Const showErrorLinesNr = True C. Det afsluttende % tegn i linie slettes D. kodelinierne gemmes som f.eks csvudpluk.vbs fil E. skal kaldes fra et console vindue sådan cscript csvudpluk >fejllinier.csv
Synes godt om
Ny brugerNybegynder
Din løsning...
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.