Avatar billede HansJorgenJK Nybegynder
23. september 2014 - 21:43 Der 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.
Avatar billede bvirk Guru
24. september 2014 - 09:31 #1
Hvad er udvalgskriteriet?

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
Avatar billede terry Ekspert
24. september 2014 - 09:24 #2
Try importing into Access.

You can find examples on youtube

EG:
https://www.youtube.com/watch?v=lwECITdxm2M
Avatar billede HansJorgenJK Nybegynder
24. september 2014 - 10:13 #3
Hej bvirk

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?
Avatar billede bvirk Guru
24. september 2014 - 12:24 #4
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?
Avatar billede HansJorgenJK Nybegynder
24. september 2014 - 12:51 #5
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.
Avatar billede bvirk Guru
24. september 2014 - 13:40 #6
Hvis du har Target Names i en flad tekstfil - et target name i hver linie:

Dim line, lineArr, outlines, tnDic
Const inpFileN = "C:\mappe\storfil.csv"
Const outFileN = "C:\mappe\lillefil.csv"
Const tNameFile = "c:\mappe\targetNames.txt"
const csvColCmp=4; ' 5 kolonne i csv fil

Set tnDic = CreateObject("Scripting.Dictionary")

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)
Avatar billede HansJorgenJK Nybegynder
24. september 2014 - 13:53 #7
jeg tester det lige.

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.
Avatar billede HansJorgenJK Nybegynder
24. september 2014 - 14:03 #8
Jeg får desværre en fejl.
Script:.....
Line: 5
Char: 18
Error: Expected end of statement
Code: 800A0401


Det kan være at det skal nævnes at der ikke er nogle headers i csv-filen. Og target name indeholder diverse tegn, dog ikke gåseøjne.
Avatar billede bvirk Guru
24. september 2014 - 14:53 #9
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.
Avatar billede HansJorgenJK Nybegynder
24. september 2014 - 15:23 #10
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
Avatar billede bvirk Guru
24. september 2014 - 15:57 #11
Nå - der har så været linier uden 4 semikoloner

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.

Dim line, lineArr, outlines, tnDic, lineNr%
Const inpFileN = "C:\mappe\storfil.csv"
Const outFileN = "C:\mappe\lillefil.csv"
Const tNameFile = "c:\mappe\targetNames.txt"
Const csvColCmp = 4 ' 5 kolonne i csv fil
Const showErrorLinesNr = False

Set tnDic = CreateObject("Scripting.Dictionary")

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
Avatar billede HansJorgenJK Nybegynder
25. september 2014 - 07:46 #12
Mange tak Bvirk :)

Du har sparet mig for mange timers arbejde.

Hvis du ligger et svar på herinde så får du dine velfortjente points.
Avatar billede bvirk Guru
25. september 2014 - 11:20 #13
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
Avatar billede Ny bruger Nybegynder

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.

Loading billede Opret Preview

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester