vytvoření makra, které nahraje z CSV souboru data a zapíše je do writeru.

Potřeboval bych napsat kód pro makro, které po spuštění otevře dialog pro nahrání souboru CSV. A následně upraví ve writeru určitá slova dle CSV souboru.
Konkrétní příklad:
Mám webové stránky, kde potencionální zákazník vyplní poptávkový formulář. Vyplněný formulář mi přijde v textové podobě do emailu. Přes google script mám nastavené automatické vytvoření CSV souboru, který se uloží do složky na google disku. CSV soubor obsahuje například tento text:
“jmeno”,“adresa”,“PSC”,“email”,“telefon”,“vymera”
“Pepa Novák”,“Praha”,“120 02”,“pepanovak@novak.cz”,“556854263”,“150”
první řádek určuje jaké slova má ve writeru nahradit a druhý řádek je, co má místo toho napsat.
ve writeru mám slova která mají být nahrazeny takto:

,


je zapsaná v tabulce ( tabulka writer, ne calc)

Už několik dní se to snažím vytvořit pomocí ChatGPT, ale každý kód co mi napíše, tak mi to hlásí nějakou chybu.

Děkuji za pomoc.

Dobry den, podívejte se prosím zde: Dokumentace | LibreOffice - Svobodný kancelářský balík - Smysluplný projekt - Skvělí lidé
Dole jsou odkazy na knihy o makrech. Pokud tam bude řešení, napište jej prosím zde do Asku.

Toto je kód, který mi konečně funguje.

Sub NahradTextZCSV()
Dim oDoc As Object
Dim oText As Object
Dim oSearch As Object
Dim sFilePath As String
Dim aLines As Variant
Dim aHeaders As Variant
Dim aValues As Variant
Dim i As Integer

' Vybrání CSV souboru
sFilePath = VyberCSV()
If sFilePath = "" Then Exit Sub ' Uživatel zrušil výběr

' Načtení obsahu CSV souboru
aLines = NactiCSV(sFilePath)
If UBound(aLines) < 1 Then
    MsgBox "CSV soubor je prázdný nebo neplatný!", 16, "Chyba"
    Exit Sub
End If

' První řádek = názvy proměnných (bez "< >")
aHeaders = Split(aLines(0), ",")
' Druhý řádek = hodnoty pro nahrazení
aValues = Split(aLines(1), ",")

' Kontrola, zda CSV obsahuje správný počet sloupců
If UBound(aHeaders) <> UBound(aValues) Then
    MsgBox "Počet hodnot neodpovídá počtu klíčových slov!", 16, "Chyba"
    Exit Sub
End If

' Získání aktuálního dokumentu
oDoc = ThisComponent
oText = oDoc.Text
oSearch = oDoc.createReplaceDescriptor()

' Prochází a nahrazuje texty v závorkách <>, zkontrolujte, zda v textu opravdu existují <> klíče
For i = 0 To UBound(aHeaders)
    oSearch.SearchString = "<" & Trim(aHeaders(i)) & ">"
    oSearch.ReplaceString = Trim(aValues(i))
    oDoc.replaceAll(oSearch)
Next i

MsgBox "Nahrazení dokončeno!", 64, "Hotovo"

End Sub

’ Funkce pro výběr CSV souboru
Function VyberCSV() As String
Dim oFilePicker As Object
oFilePicker = CreateUnoService(“com.sun.star.ui.dialogs.FilePicker”)
oFilePicker.initialize(Array(0)) ’ Pouze výběr souboru
oFilePicker.appendFilter(“CSV soubory”, “*.csv”)

If oFilePicker.execute() = 1 Then
    VyberCSV = oFilePicker.Files(0)
Else
    VyberCSV = ""
End If

End Function

’ Funkce pro načtení CSV souboru do pole
Function NactiCSV(soubor As String) As Variant
Dim oStream As Object
Dim sText As String
Dim aLines As Variant

oStream = CreateUnoService("com.sun.star.ucb.SimpleFileAccess")
If Not oStream.Exists(soubor) Then
    NactiCSV = Array()
    Exit Function
End If

Dim oInputStream As Object
oInputStream = oStream.openFileRead(soubor)

Dim oTextInputStream As Object
oTextInputStream = CreateUnoService("com.sun.star.io.TextInputStream")
oTextInputStream.setInputStream(oInputStream)
oTextInputStream.setEncoding("UTF-8")

' Čtení celého souboru
Do While Not oTextInputStream.isEOF()
    sText = sText & oTextInputStream.readLine() & Chr(10)
Loop

' Rozdělení podle řádků
aLines = Split(Trim(sText), Chr(10))

' Zavření streamu
oTextInputStream.closeInput()
oInputStream.closeInput()

NactiCSV = aLines

End Function

1 Like

Propaganda různých ChatBlbečků mě už otravuje víc než reklama, ale rozhodně palec nahoru za několikadenní samostatnou snahu udělat řešení :slight_smile:.

Zde neproprasená lidská verze.
Do konstanty cInitDir si dejte výchozí adresář kde se vám má otevírat dialog pro výběr CSV.
Hledání položek zohledňuje velikost písmen.

Sub zpracujCSV 'nahradí daty z CSV data v dokumentu
	on local error goto bug
	const cInitDir="d:\" 'výchozí adresář při výběru souboru (možno file:///.... ale i d:\...)
	const cUndo="vložení dat z CSV" 'hláška pro krok Zpět
	dim oDoc as object, sUrl$, p(), oDesc as object, p1(), p2(), i&, i1%, i2%, s1$, s2$, undoMgr as object
	rem výběr souboru
	sUrl=dialogVybratSoubor(cInitDir)
	if sUrl="" then exit sub 'nebyl vybrán soubor
	p=loadFileString(sUrl) 'pole s řádky souboru
	oDoc=ThisComponent
	
	rem odstranit úvodní a koncovou uvozovku z řádků
	s1=p(0) : s2=p(1)
	s1=Mid(s1, 2, Len(s1)-2) : s2=Mid(s2, 2, Len(s2)-2)
	rem dostat jednotlivé položky řádků
	p1=split(s1, """,""") : i1=ubound(p1) 'řetězec rozdělit raději dle "," než samotné čárky, neboť někde v těle položky by též mohla být čárka "... , ..."
	p2=split(s2, """,""") : i2=ubound(p2)
	if i1<>i2 then 'hlavička nemá stejný počet položek jako tělo
		msgbox("Hlavička: " & i1 & chr(13) & "Tělo: " & i2, 48, "Různý počet částí")
		stop
	end if
	
	rem nahradit text v dokumentu
	oDoc.lockControllers
	undoMgr=oDoc.UndoManager
	undoMgr.enterUndoContext(cUndo)
	oDesc=oDoc.createReplaceDescriptor
	oDesc.SearchCaseSensitive=true 'při nahrazování hledět na velikost písmen
	for i=0 to i1
		with oDesc
			.SearchString=p1(i)
			.ReplaceString=p2(i)
		end with
		oDoc.replaceAll(oDesc)
	next i
	
	undoMgr.leaveUndoContext()
	oDoc.unlockControllers
	exit sub
bug:
	if oDoc.hasControllersLocked() then oDoc.unlockControllers()
	if undoMgr.getCurrentUndoActionTitle=cUndo then 'byly nějaké změny v dokumentu
		with undoMgr
			.leaveUndoContext() 'uzavřít UndoManager
			.undo() 'vrátit změny
		end with
	end if
	bug(Erl, Err, Error, "zpracujCSV")
End Sub

Function dialogVybratSoubor(optional sInitDir$) as string 'dialog pro vybrání souboru
	on local error goto bug
	dim oFileDlg as object, oFileAccess as object, oFiles as object, sFile$, bDir as boolean
	rem check init directory
	if NOT isMissing(sInitDir) then 'je předán výchozí adresář
		if FileExists(sInitDir) then bDir=true 'adresář existuje
	end if	
	if bDir=False then sInitDir=CreateUnoService("com.sun.star.util.PathSettings").Work 'výchozí adresář z menu: Nástroje/Možnosti -> LibreOffice/Cesty -> Mé dokumenty
		
	oFileDlg=CreateUnoService("com.sun.star.ui.dialogs.FilePicker")
	with oFileDlg 'nastavit viditelné soubory v dialogu
		.AppendFilter("Vše (*.*)", "*.*")
		.AppendFilter("CSV (*.csv)", "*.csv")
		.SetCurrentFilter("CSV (*.csv)") 'výchozí typy souborů
	end with
	oFileAccess=CreateUnoService("com.sun.star.ucb.SimpleFileAccess")

	oFileDlg.SetDisplayDirectory( ConvertToUrl( sInitDir ) )
	if oFileDlg.execute() then 'otevřít dialog
		oFiles=oFileDlg.getFiles()
		if ubound(oFiles)>=0 then
			sFile=oFiles(0)
		end if
	end if
	dialogVybratSoubor=sFile
	exit function
bug:
	bug(Erl, Err, Error, "dialogVybratSoubor")	
End Function

Function loadFileString(sUrl$, optional sEncoding$) as variant 'načte soubor do pole (samodetekuje Enter)
	on local error goto bug
	if isMissing(sEncoding) then sEncoding="UTF-8" 'když není zadáno kódování tak předpokládat utf-8
	dim s$, oSfa as object, oTextStream as object, oStream as object, sEnter$, sLine$, aBytes(1) as byte, iLine&
	oSfa=CreateUNOService("com.sun.star.ucb.SimpleFileAccess")
	if oSfa.exists(sUrl) then 'soubor s informacemi existuje
		rem načíst celý soubor
		oStream=oSfa.openFileRead(sUrl)
		oTextStream=CreateUNOService("com.sun.star.io.TextInputStream")
		with oTextStream
			.InputStream=oStream
			.Encoding=sEncoding
			s=.readString(array(), false) 'načíst text z celého souboru
			.closeInput
		end with
		oStream.closeInput
		rem načíst první řádek a dva bajty po něm pro detekci Enteru
		oStream=oSfa.openFileRead(sUrl)
		oTextStream=CreateUNOService("com.sun.star.io.TextInputStream")
		with oTextStream
			.InputStream=oStream
			.Encoding=sEncoding
			sLine=.readLine() 'první řádek
			.InputStream.seek(Len(sLine))
			.InputStream.readBytes(aBytes, 2) 'dva bajty pro detekci Enteru
			.closeInput
		end with
		oStream.closeInput
		if ubound(aBytes)=-1 then
			msgbox("Nedetekován Enter v souboru, zřejmě jen jeden řádek" & chr(13) & sUrl, 16)
			stop
		end if
		rem detekce Enteru
		if aBytes(0)=10 then 'LF
			sEnter=chr(10) 'linux
		elseif aBytes(0)=13 then 'CR
			sEnter=chr(13) 'mac
			if aBytes(1)=10 then sEnter=chr(13) & chr(10) 'CR+LF čili win
		end if
		if sEnter="" then 'špatná detekce Enteru, vzít Enter dle systému
			select case getGuiType
			case 3 'mac
				sEnter=chr(13)
			 case 4 'linux
				sEnter=chr(10)
			case 1 'win
				sEnter=chr(13) & chr(10)
			case else 'something is wrong in detection of Enter according to OS
				msgbox("Error in OS detection of Enter :-(")
				stop
			end select
		end if
	else 'soubor s informacemi neexistuje
		msgbox("Neexistující soubor" & chr(13) & sUrl, 16)
		stop
	end if
	loadFileString=split(s, sEnter) 'vrátit pole řádků
	exit function
bug:
	bug(Erl, Err, Error, "loadFileString")
End Function

Sub bug(sErl$, sErr$, sError$, sFce$) 'zruší dialogové okno a vypíše kde se stala chyba
	msgbox("line: " & sErl & chr(13) & sErr & ": " & sError, 16, sFce)
	stop 'zastavit ať nevypisuje několik msgboxů
End Sub
1 Like