Access

  MS Access 2010+  |  Przetwarzanie tekstu  |   VBA 7.0



• Strony WWW i HTML

Co to jest format HTML.

Format HTML (Hypertext Markup Language) - to standardowy język znaczników służący do tworzenia stron internetowych i aplikacji internetowych. Znaczniki HTML, zwane inaczej tagami są podstawowymi elementami z których zbudowana jest każda strona WWW. Jest to ściśle określony specjalny tekst, umieszczony w nawiasach ostrych, np. <div>, <p>, <h1>. Znaczniki (tagi) HTML umożliwiają odpowiednie dostosowanie wyglądu strony oraz zapewnia określenie struktury dla tekstu, takich jak nagłówki, akapity, listy, linki, cytaty i inne elementy. Przeglądarki nie wyświetlają znaczników HTML, ale używają ich do interpretowania treści strony. Ponieważ my zajmujemy się tylko tekstem, nie na miejscu jest pisanie o kaskadowych arkuszach stylów (CSS) oraz języku JavaScript.

Jak ułatwić sobie pracę z HTML-em?

Jeżeli mamy kilkadziesiąt pojedynczych stron i trzeba będzie na wszystkich stronach dokonać zmian, to robienie tego „na piechotę” zajmie strasznie dużo czasu. Przewidując taki problem, powinniśmy wcześniej wyznaczyć „strategiczne” miejsca na stronie gdzie najczęściej będziemy dokonywać hurtowych zmian i nadać niektórym znacznikom identyfikatory (wiadomo unikalne), bądź oznaczyć te obszary komentarzami o określonej, indywidualnej nazwie.

<div id="mnuArt">
    <!-- a ich tag zamykający oznaczyć komentarzem -->
</div <!-- END id="mnuArt" -->

Łatwiej nam będzie zamienić zawartość całego znacznika, bez przeszukiwanie znaczników wewnątrz naszego głównego znacznika. Obszarem wymagającym najczęstszych zmian na pewno będzie obszar nawigacji. W Html5 obszar ten umieszczony jest pomiędzy znacznikiem otwierającym <nav>

<nav>
    <!-- całe menu nawigacyjne stron (strony) -->
</nav

i znacznikiem zamykającym </nav>.
Nazwy plików *.html można porzedzić prefiksami, np. api-, bmp-, docmd-, form-, plik-, tekst-, vba-, które określają poruszaną tematykę tych stron i same z siebie wymuszą pogrupowanie tematyczne stron w folderze.

Lista plików html
Przykładowa lista plików *.html

Aby hurtowo przetwarzać pliki musimy najpierw zrobić ich listę. Do tego celu wykorzystamy funkcję plikListFiles() przedstawioną na stronie API. Lista plików. Funkcja ta w argumencie ByRef sFilesPathRet() zwraca tablicę typu String zawierająca pełne nazwy znalezionych plików w folderze roboczym. Pliki możemy wyszukiwać z użyciem symboli wieloznacznych Asterisk "*" oraz QuestionMark "?".

Jeżeli struktura naszego serwisu jest bardziej rozbudowana i strony *.html znajdują się w wielu podfolderach, będziemy musieli dodatkowo skorzystać z funkcji plikListSubFoldersApi(...) wyszukującą podfoldery w folderze roboczym, która przedstawiona jest na stronie API. Lista folderów.

Mając listę plików możemy kolejno każdy plik wczytać do zmiennej sTekstHtml typu String , dokonać wymaganych zmian i zapisać plik na dysku. By wczytać plik użyjemy funkcji plikFileToString(...), która przedstawiona jest na stronie Plik do zmiennej String. Należy pamiętać, że funkcja plikFileToString(...) korzysta z pomocniczej funkcji sprawdzającej poprawność argumentów plikCheckArguments(...), która przedstawiona jest na stronie Argumenty otwarcia pliku. Jeżeli jesteśmy pewni, że plik istnieje i możemy go otworzyć bez problemów do operacji „Odczytu” i (lub) „Zapisu” to możemy zrezygnować z użycia tej funkcji.

Struktura przykładowego pliku *.html

Poniżej uproszczony plik testowy, który używany był do testów funkcji przetwarzających tekst plików *.html.

<!doctype html>
<html lang="pl">
<head>
<meta charset="UTF-8">
<meta name=viewport content="width=device-width, initial-scale=1">
<title>Przetwarzanie tekstu. Access i tekst</title>
<link rel="stylesheet" type="text/css" href="css/access.css">
<link rel="stylesheet" type="text/css" href="css/accessIndex.css">
</head><body>

<div id="container">
<header id="hdpage">
  <img src="images/banner.png" alt="Access">
  <h1 id="hdpageh1"><span>  MS Access 2010+ | Przetwarzanie tekstu | VBA 7.0</span></h1>
</header>

<section id="sect1" class="sectpage">
	<header>
	
	</header>
</section>

<nav>
	<div id="mnuArt" class="navMnu">
		<h2><a href="index.html" title="Strona główna">www.accdb.pl</a></h2>
		<div class="paddvert">
			<div id="mnuArtO" class="opis">
				<p>
					<img id="logo" src="images/logo8bit.png" alt="Logo">
					<span id="navMoje">Moje boje<br>z<br>MS Access</span>
				</p>
			</div><!-- END id="mnuArtO" -->
			<hr>
			<h2 id="navZag"><span>Zagadnienia</span></h2>
			<ul id="ul_link">
				<li><a href="api.html" title="Lista artykułów o API">API</a></li>
				<li><a href="bmp.html" title="24-bitowa bitmapa">Bitmapa</a></li>
				<li><a href="docmd.html" title="Metody obiektu DoCmd">DoCmd - metody</a></li>
				<li><a href="form.html" title="O formularzach">Formularze</a></li>
				<li><a href="funkcja.html" title="Wbudowane funkcje">Funkcje VBA</a></li>
				<li><a href="instrukcja.html" title="Instrukcje VBA">Instrukcje VBA</a></li>
				<li><a href="akcja.html" title="Akcja (makro)">Makra - (Akcje)</a></li>
				<li><a href="metoda.html" title="Metody w MS Access">Metody obiektów</a></li>
				<li><a href="plik.html" title="Operacje na plikach">Pliki</a></li>
				<li><a href="tekst.html" title="Przetwarzanie tekstu">Tekst</a></li>
				<li><a href="wlasciwosc.html" title="Właściwości MS Access">Właściwości obiektów</a></li>
				<li><a href="vba.html" title="Artykułów o VBA">VBA</a></li>
				<li><a href="zdarzenie.html" title="Zdarzenia w MS Access">Zdarzenia (events)</a></li>
				</ul>
		</div><!-- END id="paddvert" -->
	</div><!-- END id="mnuArt" -->

	<div id="mnuAcc" class="navMnu">
		<h2>Przetwarzanie tekstu</h2>
		<div class="paddvert">
			<div id="mnuAccO" class="opis">
				<p>
					<span>
						Jakiś tekst … Opis zagadnień …
					</span>
				</p>
			</div><!-- END id="mnuAccO" -->
			<ul id="nav_art">
				<li><a href="tekst.html" title="Funkcje MS Access">Spis. Przetwarzanie tekstu</a></li>
				<li><a href="tekst-isunicode.html" title="Czy Unicode">tekstIsUnicode(...)</a></li>
				<li><a href="tekst-ascii-to-utf8.html" title="ASCI na UTF8">ASCII »» UTF8.</a><li>
				<li><a href="tekst-utf8-to-ascii.html" title="UTF8 na ASCI">UTF8 »» ASCII.</a><li>
			</ul>
		</div>
	</div><!-- END id="mnuAcc" -->
</nav>

<aside>
	<!-- tekst Aside -->
</aside>

<footer>
	<!-- tekst footer -->
</footer>

</div><!-- END id="container" -->
</body></html>
 

Odczyt tekstu pomiędzy identyfikatorami (tagami, znacznikami).

Jeżeli dobrze oznaczyliśmy „strategiczne” miejsca w pliku *.html za pomocą identyfikatorów, bądź komentarzy o określonej, indywidualnej nazwie to możemy przystąpić do dzieła ....
Plik *.html mamy już zapisany w zmiennej sTekstHtml, więc za pomocą funkcji InStr pobieramy wystąpienia tagu startowego, następnie pozycję tagu końcowego, a pomiędzy tymi tagami, a raczej za pozycją ostatniego znaku tagu startowego i przed pozycją pierwszego znaku tagu końcowego znajduje się szukany tekst. Mając określoną pozycję pierwszego i ostatniego znaku szukanego tekstu, za pomocą funkcji Mid pobieramy tekst z ciągu wejściowego.

⊗ Public Function tekstExtractTextFromHtml( _
                      sTextHtml As String, _
                      sTagStart As String, _
                      sTagEnd As String, _
             Optional lStart As Long = 1, _
             Optional lRetEndPos As Long = 0) As String
  • Pobiera z wejściowego ciągu znaków sTextHtml podciąg znaków, zawarty pomiędzy tagiem (znacznikiem) startowym sTagStart, a tagiem (znacznikiem) końcowym sTagEnd.
  • argumenty:
    • sTextHtml
    • wejściowy ciąg znaków, z którego ma zostać pobrany tekst znajdujący się pomiędzy tagiem (znacznikiem) początkowym sTagStart i tagiem (znacznikiem) końcowym sTagEnd,
    • sTagStart
    • tag (znacznik) początkowy, za którym znajduje się tekst do pobrania,
    • sTagEnd
    • tag (znacznik) końcowy, określający koniec tekstu do pobrania,
    • lStart
    • argument nieobowiązkowy. Domyślna wartość = 1. Pozycja znaku od której będzie szukany tag (znacznik) początkowy. Dla wartości argumentu lStart < 1 generowany jest błąd wykonania o numerze errInvalidStart = vbObjectError + err_plikError + 1, (err_plikError = 100), Dla wartości argumentu lStart > Len(sTextHtml) (większy niz długość ciągu wejściowego) generowany jest błąd wykonania o numerze errStartEOF = vbObjectError + err_plikError + 11, (err_plikError = 100),
    • lRetEndPos
    • argument nieobowiązkowy. Domyślna wartość = 0. Bez względu na przekazaną wartość zwracana jest ByRef pozycja ostatniego znaku tagu (znacznika) końcowego sTagEnd. Znajomość pozycji ostatniego znaku tagu końcowego umożliwia w następnym wywołaniu funkcji, szukanie tagu startowego i końcowego za pozycją bieżącego tagu końcowego. Istotne, gdy w zmiennej sTextHtml występuje więcej tagów (znaczników) o tej samej nazwie np. <section>, <header>, <h1>, <h2>,
  • zwraca:
  • Przy powodzeniu zwraca ciąg znaków znajdujący się pomiędzy tagiem (znacznikiem) startowym sTagStart, a tagiem (znacznikiem) końcowym sTagEnd.
    Przy niepowodzeniu zwraca ciąg zerowej długości "".
  • autor: Zbigniew Bratko
  • data: 09.02.2018
Option Compare Database
Option Explicit

'dolna granica zakresu numerów błędów dotyczących plików
Private Const err_plikError       As Long = 100
' Numer początkowy bajtu (znaku, linii), nie może być mniejszy niż 1

Private Const errInvalidStart     As Long = vbObjectError + err_plikError + 1
' W pliku wejściowym nie istnieje szukany podciąg znaków
Private Const errNotInString      As Long = vbObjectError + err_plikError + 10
' Pozycja startowa wyszukiwania jest większa niż długość ciągu wejściowego
Private Const errStartEOF         As Long = vbObjectError + err_plikError + 11


Public Function tekstExtractTextFromHtml( _
                      sTextHtml As String, _
                      sTagStart As String, _
                      sTagEnd As String, _
             Optional lStart As Long = 1, _
             Optional lRetEndPos As Long = 0) As String

On Error GoTo Err_Handler
Dim lInStrStart   As Long
Dim lInStrEnd     As Long
Const conProcName As String = "Funkcja tekstExtractTextFromHtml(...)"

  ' pozycja znaku startowego nie może być mniejsza od Zera
  If lStart < 1 Then
    Err.Raise errInvalidStart
  End If
  
  ' pozycja znaku startowego nie może być większa niż długość ciągu
  If lStart > Len(sTextHtml) Then
    Err.Raise errStartEOF
  End If
 
  ' pobierz pozycję tagu startowego
  lInStrStart = InStr(lStart, sTextHtml, sTagStart, vbBinaryCompare)
  If lInStrStart = 0 Then
    Err.Raise errNotInString, , _
            " początkowy " & sTagStart & " za znakiem nr " & lStart
  End If

  ' pobierz pozycję tagu końcowego, zacznij szukać za ostatnim znakiem tagu startowego
  lInStrEnd = InStr(lInStrStart + Len(sTagStart), sTextHtml, sTagEnd, vbBinaryCompare)
  If lInStrEnd = 0 Then
    Err.Raise errNotInString, , _
            " końcowy " & sTagEnd & " za znakiem nr " & (lInStrStart + Len(sTagStart))
  End If
  
  ' oblicz pozycję początkową tekstu do pobrania
  lInStrStart = lInStrStart + Len(sTagStart)
  
  ' zwróć ByRef pozycję ostatniego znaku tagu końcowego, by umożliwić w następnym
  ' wywołaniu szukanie tagu startowego i końcowego za pozycją bieżącego tagu końcowego
  lRetEndPos = lInStrEnd + Len(sTagStart)
  
  ' pobierz tekst pomiędzy tagami
  tekstExtractTextFromHtml = Mid$(sTextHtml, lInStrStart, lInStrEnd - lInStrStart)

Exit_Here:
  Exit Function

Err_Handler:
  Select Case Err.Number
    Case 0 ' nie ma błędu
    Case errInvalidStart
      Err.Raise errInvalidStart, conProcName, _
                  "Niewłaściwa wartość argumentu lStart." & vbNewLine & _
                  "Prawidłowo: [lStart] > 0"
    Case errNotInString
      Err.Raise errNotInString, conProcName, _
                "Identyfikator " & Err.Description & " nie istnieje !"
    Case errStartEOF
      Err.Raise errStartEOF, conProcName, _
                "Niewłaściwa wartość argumentu lStart." & vbNewLine & _
                "Przekroczona długość ciągu wejściowego"
    Case Else
      Err.Raise Err.Number, conProcName, _
                "Nieprzewidziany błąd!" & vbNewLine & _
                Err.Description
  End Select
  Resume Exit_Here

End Function
 

Zamiana tekstu pomiędzy identyfikatorami (tagami, znacznikami).


⊗ Public Function tekstInsertTextInHtml( _
                        sTextHtml As String, _
                        sTagStart As String, _
                        sTagEnd As String, _
                        sInsertText As String, _
               Optional lStart As Long = 1, _
               Optional lRetEndPos As Long = 0) As String
  • Zamienia w wejściowym ciągu znaków sTextHtml podciąg znaków, zawarty pomiędzy tagiem (znacznikiem) startowym sTagStart, a tagiem (znacznikiem) końcowym sTagEnd na ciąg znaków sInsertText.
  • argumenty:
    • sTextHtml
    • wejściowy ciąg znaków, w którym tekst zawarty pomiędzy tagami (znacznikami) początkowym i końcowym, ma zostać zamieniony na tekst sInsertText
    • sTagStart
    • tag (znacznik) początkowy, za którym ma być wstawiony tekst sInsertText. Tekst pomiędzy tagiem (znacznikiem) początkowym sTagStart a tagiem (znacznikiem) końcowym sTagStart zostaje w całości zastąpiony.
    • sTagEnd
    • tag (znacznik) końcowy, wyznaczający końcową pozycję wstawianego tekstu. Tekst pomiędzy tagiem (znacznikiem) początkowym sTagStart a tagiem (znacznikiem) końcowym sTagStart zostaje w całości zastąpiony.
    • sInsertText
    • tekst, który ma być wstawiony pomiędzy tagiem (znacznikiem) początkowym sTagStart a tagiem (znacznikiem) końcowym sTagStart
    • lStart
    • argument nieobowiązkowy. Domyślna wartość = 1. Pozycja znaku od której będzie szukany tag (znacznik) początkowy. Dla wartości argumentu lStart < 1 generowany jest błąd wykonania o numerze errInvalidStart = vbObjectError + err_plikError + 1, (err_plikError = 100), Dla wartości argumentu lStart > Len(sTextHtml) (większy niz długość ciągu wejściowego) generowany jest błąd wykonania o numerze errStartEOF = vbObjectError + err_plikError + 11, (err_plikError = 100),
    • lRetEndPos
    • argument nieobowiązkowy. Domyślna wartość = 0. Bez względu na przekazaną wartość zwracana jest ByRef pozycja ostatniego znaku tagu (znacznika) końcowego sTagEnd. Znajomość pozycji ostatniego znaku tagu końcowego umożliwia w następnym wywołaniu funkcji, szukanie tagu startowego i końcowego za pozycją bieżącego tagu końcowego. Istotne, gdy w zmiennej sTextHtml występuje więcej tagów (znaczników) o tej samej nazwie np. <section>, <header>, <h1>, <h2>,
  • zwraca:
  • Przy powodzeniu zwraca ciąg znaków z wprowadzonymi zamianami, od pozycji określonej przez argument lStart aż do pozycji określonej przez argument lRetEndPos.
    Przy niepowodzeniu zwraca ciąg zerowej długości "".
  • autor: Zbigniew Bratko
  • data: 09.02.2018
Option Compare Database
Option Explicit

'dolna granica zakresu numerów błędów dotyczących plików
Private Const err_plikError       As Long = 100
' Numer początkowy bajtu (znaku, linii), nie może być mniejszy niż 1

Private Const errInvalidStart     As Long = vbObjectError + err_plikError + 1
' W pliku wejściowym nie istnieje szukany podciąg znaków
Private Const errNotInString      As Long = vbObjectError + err_plikError + 10
' Pozycja startowa wyszukiwania jest większa niż długość ciągu wejściowego
Private Const errStartEOF         As Long = vbObjectError + err_plikError + 11


Public Function tekstInsertTextInHtml( _
                        sTextHtml As String, _
                        sTagStart As String, _
                        sTagEnd As String, _
                        sInsertText As String, _
               Optional lStart As Long = 1, _
               Optional lRetEndPos As Long = 0) As String

On Error GoTo Err_Handler
Dim lInStrStart   As Long
Dim lInStrEnd     As Long
Const conProcName As String = "Funkcja tekstInsertTextInHtml(...)"

  ' pozycja znaku startowego nie może być mniejsza od Zera
  If lStart < 1 Then
    Err.Raise errInvalidStart
  End If
  
   ' pozycja znaku startowego nie może być większa niż długość ciągu
  If lStart > Len(sTextHtml) Then
    Err.Raise errStartEOF
  End If

  ' pobierz pozycję tagu startowego
  lInStrStart = InStr(1, sTextHtml, sTagStart, vbBinaryCompare)
  If lInStrStart = 0 Then
    Err.Raise errNotInString, , " początkowy " & sTagStart
  End If
  
  ' pobierz pozycję tagu końcowego, zacznij szukać za ostatnim znakiem tagu startowego
  lInStrEnd = InStr(lInStrStart + Len(sTagStart), sTextHtml, sTagEnd, vbBinaryCompare)
  If lInStrEnd = 0 Then
    Err.Raise errNotInString, , " końcowy " & sTagEnd
  End If
  
  ' zwróć ByRef pozycję ostatniego znaku tagu końcowego, by umożliwić w następnym
  ' wywołaniu szukanie tagu startowego i końcowego za pozycją bieżącego tagu końcowego
  lRetEndPos = lInStrEnd + Len(sTagStart)

  ' wstaw tekst pomiędzy tagami
  tekstInsertTextInHtml = _
        Left$(sTextHtml, lInStrStart - 1 + Len(sTagStart)) & _
        sInsertText & _
        Mid$(sTextHtml, lInStrEnd)

Exit_Here:
  Exit Function

Err_Handler:
  Select Case Err.Number
    Case 0 ' nie ma błędu
    Case errInvalidStart
      Err.Raise errInvalidStart, conProcName, _
                  "Niewłaściwa wartość argumentu lStart." & vbNewLine & _
                  "Prawidłowo: [lStart] > 0"
    Case errNotInString
      Err.Raise errNotInString, conProcName, _
                "Identyfikator " & Err.Description & " nie istnieje !"
    Case errStartEOF
      Err.Raise errStartEOF, conProcName, _
                "Niewłaściwa wartość argumentu lStart." & vbNewLine & _
                "Przekroczona długość ciągu wejściowego"
    Case Else
      Err.Raise Err.Number, conProcName, _
                "Nieprzewidziany błąd!" & vbNewLine & _
                Err.Description
  End Select
  Resume Exit_Here

End Function