Hulp bij string zaken ivm conversie locatie bestanden

Status
Niet open voor verdere reacties.

bikerron

Gebruiker
Lid geworden
9 mei 2009
Berichten
229
Een goededag,
Het is al weer enige tijd geleden dat ik mij beziggehouden heb met Access en ik ben nu gevraagd een soort conversie uit te voeren.

De eigenaar van de applicatie wil op zijn PC/Laptop een andere directory structuur, deze structuur is terug te vinden in een applicatie binnen een tabel.
Ergo... de waarden van een veld moet worden geconverteerd naar de nieuwe structuur.
Het gaat om afbeeldingen waarnaartoe verwezen wordt, dus als de afbeelding op de PC/Laptop in een andere directory geplaatst is dan zal de locatie binnen het veld van de tabel ook moeten worden aangepast.

De situatie is als volgt:
In de tabel heb ik een kolom Image
De inhoud is:
MiniatuurKoppel1
../../Ship/Slowakije/min/Muflon%208%20Bratislava%208457007 (Koppel%201).jpg#../../Ship/Slowakije/min/Muflon%208%20Bratislava%208457007%20(Koppel%201).jpg#

Vertaald dus: in de Directory ../../Ship/Slowakije/min is de afbeelding op de PC/Laptop geplaatst.

De nieuwe situatie moet zijn:
MiniatuurKoppel1
../../Ship/Slowakije/M/min/Muflon%208%20Bratislava%208457007 (Koppel%201).jpg#../../Ship/Slowakije/min/Muflon%208%20Bratislava%208457007%20(Koppel%201).jpg#

Vertaald:
er zal dus een subdirectory gemaakt moeten worden, de EERSTE letter dat voorkomt NA /min/ Directory Ship/Slowakije/M/min ........ moet het gaan worden.
Dus er zal "gezocht" moeten worden naar de vierde
Vervolgens de EERSTE letter NA min/
Deze letter plaatsen als hoofdletter NA de derde /, dus direct voor de /min.

Is hiervoor een conversie string te bedenken?

Deze te converteren records bevinden zich in een tabel van 40.000 records en zijn een van de eerste records, er komen dus records voor die wel al voorzien zijn van een subdirectory in de juiste vorm.


Bij voorbaat dank,

Ron
 
Dit is exact de reden dat ik alleen de bestandsnamen opsla van afbeeldingen, en nooit het hele pad. Zelf zet ik dan het gebruikte pad in een constante (sPad bijvoorbeeld) en als ik dan een ander pad nodig heb, dan verander ik alleen de constante en ik kan weer aan het bier. Jij zo te zien nu niet :).
Daarnaast krijg ik de indruk dat je ook nog eens hyperlink velden gebruikt, en ook dat heb ik van mijn hele leven nog nooit gedaan of nodig gehad. Gewoon tekstvelden gebruiken en de opdracht FollowHyperlink, bijvoorbeeld bij een dubbelklik en je hebt precies hetzelfde resultaat, maar ontiegelijk makkelijker te beheren. Maar goed, je kiest voor de moeilijke weg dus heb je ook een moeilijke oplossing nodig. Die is er ook wel denk ik; met het SPLIT commando kun je een variabele in een matrix inlezen. Die matrix kun je dan vervolgens weer uitlezen en opnieuw samenstellen, met de nieuwe component ertussen. Ik zou daar een functie voor maken i.c.m. een recordset die dan de records uitleest, de oude dus m.b.v. Split in een matrix zet, opnieuw opbouwt en weer wegschrijft in de tabel. Hier een voorbeeldje hoe je met Split de bestandsnaam uitleest:
Code:
    MsgBox Split("../../Ship/Slowakije/min/Muflon%208%20Bratislava%208457007%20(Koppel%201).jpg", "/") _
        (UBound(Split("../../Ship/Slowakije/min/Muflon%208%20Bratislava%208457007%20(Koppel%201).jpg", "/")))
 
Hallo Octafish,
Dank voor de reactie, ik heb wat uit te zoeken.
De Access applicatie is nu ong. 10 jaar oud en is a.h.v een Excel bestand ooit omgezet.
Ik begrijp je standpunt aangaande niet opslaan van een directorystructuur bij een bestandsnaam. Ik zie echter even niet hoe dat de realiseren zou zijn.
De directorystructuur is op zichzelf ook variabel met volgende betekenis :
Hoofddirectory, Land (code), eerste letter van afbeelding, type afbeelding
Daarachter dus bestandsnaam.
Als ik de directorystructuur wil opslaan in variabelen dan heb ik er nogal wat nodig denk ik zo.
Een voor elke de land(code), 26 voor de letters.
Of....... zie ik het allemaal te ingewikkeld.?

Evengoed.... ik ga je voorstel probreren toe te passen.
Ron
 
Ik zou, om te beginnen, afstappen van die hyperlinks; het is nogal een vervelende klus om die te 'vertalen' naar een andere directory vorm omdat de verwijzingen er twee keer in staan. Nog afgezien van de idiote manier van spaties wegschrijven, wat in een normaal tekstveld uiteraard geen enkel probleem is maar in een hyperlink wel (%20).
Ik heb je vraag in eerste instantie een beetje verkeerd geïnterpreteerd (wel het goede antwoord gegeven trouwens, dat verandert niet). Maar zelfs met die interpretatie kan het nog steeds makkelijker. De basis locatie is dus voor elke foto gelijk, en die gebruik je dan als constante. De eerste variabele map is dan dus de eerste letter van de bestandsnaam, en omdat dat dát in essentie óók weer een vast gegeven is (Left(bestandsnaam,1) is dat dus óók heel simpel te genereren in een hyperlink. En hoef je dat 'vaste' deel van de naam dus ook niet op te slaan. Desnoods maak je twee constanten: één voor het eerste deel, en een voor het tweede deel. Het 'koppelstuk' is dan de eerste letter uit de bestandsnaam.
 
Ben er mee bezig geweest, eerst maar eens buiten een formulier of Vba om, maar op de een of ander manier doe ik iets fout en de Help functie van Access geeft mij niet de oplossing of..... ik lees niet goed.
Ik heb een tabel fotos, met daarin de kolom MiniatuurFoto1

Ik wil dus de Split functie loslaten op de kolom MiniatuurFoto1
Ik doe dat alsvolgt;
HTML:
SELECT fotos.Registernummer, fotos.MiniatuurFoto1,

Expr1: Split([MiniatuurFoto1];"/";3)

FROM fotos;

Boodschap is: De expressie bevat een ongedefinieerde functie Split :(

Ron
 
En daar heb je de reden voor de foutmelding :). Je probeert in een query een VBA functie los te laten en dat gaat niet. Als je de functie had geprobeerd te maken met de Function Builder, dan had je daar ook geen functie Split tussen zien staan. Wil je de functie toch in een query hebben, dan moet je een UDF (User Defined Function) van maken, een eigen functie dus. Die krijgt dan het veld als input en levert zelf een string als output.
Overigens is er nóg een reden waarom jouw opzet niet werkt, en die had je kunnen bedenken als je mijn eerdere antwoord had begrepen. Het Split commando levert namelijk een matrix variabele op, en dat op zich is al een NoNo in een query, waarin je alleen velden met één waarde kan plaatsen, geen matrix dus.
 
Ha,
Ja, mijn kennis van VBA is minimaal.
Maar ik heb de Split met resultaat in array's via MSGBOX duidelijk, ik moest daar echter wel eerst voor de het veld van Hyperlink omzetten naar Tekst.
Waar ik nog mee worstel is:
Hoe kan ik de inhoud van de Array's "opslaan" in de tabel.
Ik heb een extra veld aangemaakt, "Bestand", Tekst.
Deze in een formulier mee laten komen, is uiteraard leeg.
Als ik op het veld klik waar de "Split" op moet gaan werken dan wil ik dus het resultaat terugzien in vel "Bestand" en uiteraard in de tabel zelf.
He je nog een tipje van een sluier voor mij?

Ron
 
Maar ik heb de Split met resultaat in array's via MSGBOX duidelijk, ik moest daar echter wel eerst voor de het veld van Hyperlink omzetten naar Tekst.
Kon wel eens het beste plan van de week zijn voor je :). En nu nooit meer gebruiken, die Hyperlink velden :D.
Voor het opslaan van de nieuwe string moet je dus een procedure maken die op de door mij aangegeven manier de string splitst en weer samenstelt. Die procedure moet m.b.v. een recordset dus alle records doorlopen en het tekstveld uitlezen, de string opnieuw opbouwen en weer wegschrijven. An sich niet zo'n moeilijke procedure.

Wil je het via het formulier doen, dan kun je dezelfde procedure gebruiken maar dan zonder de recordset.
 
Nou weer wat verder, ben er in geslaagd de uitgevlooide data uit de string te halen, zie afbeelding "Msgbox".
De daarna opgeslagen inhoud, ik dacht dat dat dan de bestandsnaam is, werd vertaald als een "1". zie afbeelding

Hierbij de door mij gebruikte code:
Code:
Private Sub Tekst11_Click()
Dim bestand As String
bestand = MsgBox(Split([MiniatuurFoto1], "/") _
        (UBound(Split([MiniatuurFoto1], "/"))))
MsgBox (bestand)

Me.Tekst11 = bestand
End Sub
Wat zie ik over het hoofd?Resultaat.PNGMsgbox.PNG

Ron
 
Ga even in een rustig hoekje staan, want je gaat jezelf een stukkie voor je kop slaan :).
Code:
    bestand = (Split(Me.MiniatuurFoto1, "/")(UBound(Split(Me.MiniatuurFoto1, "/"))))
 
Even offline geweest.
In weekend gepoogd een update over de volledige tabel te realiseren via VBA.
Lou Loenen dus.
Maar goed ik klop toch maar even aan want ik wil de conversie gerealiseerd zien te krijgen nietwaar.
Wat heb ik gebakken (via zoeken in forum en naar eigen inzicht aangepast)

Onder de Option Compare Database
Code:
Sub cnv()

    Dim rs As Object
    Dim cnv_bestand As String

  Dim strSQL As String
  Dim rst As DAO.Recordset
  cnv_bestand = (Split([MiniatuurFoto1], "/")(UBound(Split([MiniatuurFoto1], "/"))))


    strSQL = "SELECT [Me.FotoID],[Me.Registernummer],[ME.MiniatuurFoto1],[Me.bestand] FROM [CNV-fotos]"
    Set rst = CurrentDb.OpenRecordset(strSQL)
    With rst
        Do While Not .EOF
            .Edit
            !Me.bestand = cnv_bestand
            .Update
        Loop
        .Close
    End With
End Sub
De bedoeling is dus dat alle records in 1 keer worden geupdated. Het veld "Me.bestand" moet de inhoud krijgen van de string cnv_bestand.

Waar ga ik de mist in?
 
Laatst bewerkt:
Er zitten nogal wat fouten in je code, dus ik snap dat die zo niet werkt :).
Om te beginnen: je gebruikt het woord 'Me' verkeerd.
Het veld "Me.bestand" moet de inhoud krijgen van de string cnv_bestand.

Je veld heet ongetwijfeld [bestand] en niet [Me.bestand]. 'Me.' gebruik je om naar objecten te verwijzen, niet naar velden en je kunt [Me.bestand] dus nooit in een query gebruiken. Je maakt de fout dus verderop nog een keer, als je de tabel bijwerkt:
Code:
            !Me.bestand = cnv_bestand
Dat moet dan zo:
Code:
            !bestand = cnv_bestand
Ik dacht na eerste lezing dat je op een formulier (vandaar de knop) het huidige record wilde aanpassen. Dat kan veel simpeler:
Code:
    Me.bestand = (Split([MiniatuurFoto1], "/")(UBound(Split([MiniatuurFoto1], "/"))))
De knop krijgt dus maar één regel code.

Maar je blijkt dus alles te willen bijwerken, en dat kan dan op twee manieren: met een recordset, of een bijwerkquery. Ik zou in dit geval de bijwerkquery kiezen.
Code:
Sub cnv()
Dim strSQL As String
  
    strSQL = "UPDATE [CNV-fotos] SET bestand = """ & Split([MiniatuurFoto1], "/")(UBound(Split([MiniatuurFoto1], "/"))) & """ WHERE FotoID = " & Me.FotoID
    CurrentDb.Execute strSQL, dbFailOnError

End Sub
 
Weer veel dank voor te toelichtingen.
Nu het volgende. Ik snap dat je in een soort loop de tabel moet laten doorlopen, althans daar ga ik van uit.
Ik heb diverse opties doorgenomen maar loop toch stuk op error's
Wat heb ik nu:
Code:
Private Sub Form_Load()
Dim db As DAO.Database
Dim rs As DAO.Recordset
Dim strSQL As String

Set db = CurrentDb()
    strSQL = "UPDATE [CNV-fotos] SET bestand = """ & Split([MiniatuurFoto1], "/")(UBound(Split([MiniatuurFoto1], "/"))) & """ WHERE FotoID = " & Me.FotoID
    MsgBox (strSQL)
    MsgBox (Me.bestand)
   CurrentDb.Execute strSQL, dbFailOnError

End Sub
Er wordt slechts 1 record getoond maar het volgende record wordt niet opgepakt.
Dus ik dacht een statement als With, For Next, Loop maar wat ik ook toepas.... allemaal error's
Heb je nog een hint, of oplossing:(
 
Deze query update ook maar één record, namelijk degene die als eerste in de lijst staat. Ik had de query in twee varianten gemaakt, voor het huidige record en voor alle records. In het eerste geval gebruik je een filter, in het tweede niet. Omdat je de foto uit het eerste record haalt (Me.MiniatuurFoto1) ging ik er vanuit dat je per record wilt bijwerken. Vandaar het filter. Als het eerste record gebruikt wordt voor alle records, kan de WHERE weg.
 
Oke, ik heb zitten stoeien met het updaten.
Als ik onderstaande code gebruik in VBA worden alle records ge-update met de inhoud van het eerste record, beetje vreemd nietwaar :confused:
Code:
Private Sub Form_Load()
Dim db As DAO.Database
Dim rs As DAO.Recordset
Dim strSQL As String

Set db = CurrentDb()
    strSQL = "UPDATE [CNV-fotos] SET [bestand] = """ & Split([MiniatuurFoto1], "/")(UBound(Split([MiniatuurFoto1], "/"))) & """ WHERE MiniatuurFoto1 <> """""
    MsgBox (strSQL)
    MsgBox (Me.bestand)
    MsgBox (bestand)
CurrentDb.Execute strSQL, dbFailOnError

End Sub
Ik heb toen maar even een test met een update Query gedaan met SQL en daar werd de update keurig uitgevoerd voor elk record een andere waarde in veld bestand :)
Code:
SELECT [CNV-fotos].FotoID, [CNV-fotos].Registernummer, [CNV-fotos].Volgnummer, [CNV-fotos].MiniatuurFoto1, Len([CNV-fotos]![MiniatuurFoto1]) AS lengte
FROM [CNV-fotos]
WHERE ((([CNV-fotos].MiniatuurFoto1)<>""));

Wat is het verschil, behalve de Split en Ubound, tussen deze 2 update opdrachten.
Split en Update vanuit VBA op een formulier
Ron
 
Als ik onderstaande code gebruik in VBA worden alle records ge-update met de inhoud van het eerste record, beetje vreemd nietwaar
De code die je hieronder laat zien, doet exact wat je beschrijft en daar is één reden voor: de code heeft namelijk de opdracht om exact dat uit te voeren. Als je dat vreemd vind, dan heb je een tijdje met mijn vriendin samengewoond; die doet namelijk ook namelijk nooit wat ik haar opdraag. Doet ze dat wél, dan ben ik dus ook totaal :confused:.
Ik ben op mijn beurt dan weer verbaasd over jouw tweede voorbeeld: dat ís namelijk geen Update query, maar een simpele selectie query. Ik schrijf ze overigens liever een stuk korter:
PHP:
SELECT FotoID, Registernummer, Volgnummer, MiniatuurFoto1, Len([MiniatuurFoto1]) AS lengte FROM [CNV-fotos] WHERE MiniatuurFoto1)<>""
Daar kun je dus nooit een tabel mee bijwerken. Hooguit als basis gebruiken voor een update query, maar van deze kun je natuurlijk ook wel een bijwerkquery maken.
 
Dat er nog vriendinnen zijn die iets laten opdragen, maar goed daar gaat het niet om.
De voorbeeld query was inderdaad een selectie, ik had dus niet moeten schrijven update, hoewel ik wel een update met die opdrachten had toegepast.
Dus... als ik met VBA elk afzonderlijk record zou willen updaten mist er nog een stukkie code. Wil je nog een richting aangeven?
 
Als ik zou weten wat je met die update query aan het updaten ben, kan ik wel een voorzetje geven. Zoals ik al in #14 al zei kun je best met een update query werken. Al ging ik er in mijn voorbeeld vanuit dat je alles, of een selectie (huidig record) met één waarde wilde vullen. Want dat maakte ik op uit jouw code. Dat blijkt dus niet zo te zijn. Als ik de code er nog even bijpak, deze:
Code:
Sub cnv()
Dim strSQL As String
    strSQL = "UPDATE [CNV-fotos] SET bestand = """ & Split([MiniatuurFoto1], "/")(UBound(Split([MiniatuurFoto1], "/"))) & """ WHERE FotoID = " & Me.FotoID
    CurrentDb.Execute strSQL, dbFailOnError
End Sub
dan werkt die alle records bij op basis van de huidige foto. Als dat niet de bedoeling is, zoals je schreef, dan kon je het laatste stuk weghalen, was toen mijn antwoord. Dan krijg je dus dit:
Code:
Sub cnv()
Dim strSQL As String
    strSQL = "UPDATE [CNV-fotos] SET bestand = """ & Split([MiniatuurFoto1], "/")(UBound(Split([MiniatuurFoto1], "/")))
    CurrentDb.Execute strSQL, dbFailOnError
End Sub
En deze query werkt dus alle records bij op basis van de string die in het eigen record staat.
Met
Code:
     tmp = Inputbox("","",strSQL)
kun je de SQL nog uitlezen en testen in een query, als je de tekst kopieert en in een nieuwe query plakt. Die zou dan moeten werken.
 
Status
Niet open voor verdere reacties.
Steun Ons

Nieuwste berichten

Terug
Bovenaan Onderaan