Jak wyodrębnić określone informacje z dokumentu programu Word, a następnie wykorzystać je w celu zmiany nazwy dokumentu?
Skrypciarze odpowiadają na Wasze pytania
Witamy w rubryce TechNet, w której Skrypciarze z firmy Microsoft odpowiadają na częste pytania dotyczące używania skryptów w administracji systemu. Jeśli macie jakieś pytania z tej dziedziny, zachęcamy do wysłania e-maila na adres: scripter@microsoft.com. Nie możemy zagwarantować odpowiedzi na każde otrzymane pytanie, ale staramy się jak możemy. |
Jak wyodrębnić określone informacje z dokumentu programu Word, a następnie wykorzystać je w celu zmiany nazwy dokumentu?
Cześć, Skrypciarze! Mam kilka dokumentów programu Word w folderze. Muszę otworzyć każdy z dokumentów, wczytać niektóre informacje z pierwszych dwóch wierszy, a następnie zastosować te informacje w celu zmiany nazwy pliku. Mam jednak pewne problemy z wykonaniem tego zadania.
-- TG
Cześć, TG. Jak wiedzą wszyscy wierni czytelnicy rubryki Cześć, Skrypciarze!, jestem zazwyczaj całkiem pochłonięty swoją pracą: nigdy nie pozwalam na to, żeby coś mnie od niej odciągnęło i utrudniało odpowiedź na pytanie dotyczące skryptów administrowania systemem. Dziś jednak muszę zrobić pewien wyjątek: ta historia jest po prostu zbyt niesamowita, żebym mógł ją pominąć.
W ubiegłym tygodniu zmarł we śnie pewien staruszek. Jego współlokatorzy – chcąc zapewne oddać mu w ten sposób ostatnią przysługę – zdecydowali się odebrać za niego emeryturę na poczcie. Kiedy tam poszli okazało się, że osoba, której należy się wypłata, powinna być przy tym obecna. Wobec tego współlokatorzy wrócili do domu, ubrali denata najlepiej jak potrafili, posadzili na biurowym krześle i przyciągnęli przed budynek poczty. Zostawili go tam na chodniku i poszli do kasy po emeryturę. Aby nie przedłużać: zgromadziło się wokół niego sporo gapiów, pojawił się policjant, żeby sprawdzić o co chodzi, a uczynni współlokatorzy zostali aresztowani. Twierdzili oni, że nie mieli pojęcia, że ich kolega jest martwy, ponieważ „wyglądał dokładnie tak, jak każdego ranka”. „Nie wiedziałem, że nie żyje. Kolega miał $500 w kieszeni, a ja $200. Po co miałbym go okradać?”
Innymi słowy, ich znajomy wyglądał tak martwo każdego ranka. Ciężko w to uwierzyć? Może. Ale przecież nikt z Was nie widział nigdy mnie i nie wie, jak ja wyglądam rano.
Jak już mówiłem, nie mogłem nie opowiedzieć Wam tej historii. Teraz czas zająć się tym, za co mi płacą. Marnie, ale zawsze. Zatem potrzebny nam skrypt otwierający dokument programu Microsoft Word (a raczej całą masę dokumentów), który pobierze pewne informacje z pierwszych dwóch wierszy i wykorzysta je do zmiany nazwy pliku. Jak to zrobić? Oczywiście używając poniższego skryptu:
Set objWord = CreateObject("Word.Application")
objWord.Visible = True
Set objDoc = objWord.Documents.Open("C:\Scripts\Test.doc")
strText = objDoc.Paragraphs(1).Range.Text
arrText = Split(strText, vbTab)
intIndex = Ubound(arrText)
strUserName = arrText(intIndex)
arrUserName = Split(strUserName, " ")
intLength = Len(arrUserName(1))
strName = Left(arrUserName(1), intlength - 1)
strUserName = strName & ", " & arrUserName(0)
strText = objDoc.Paragraphs(2).Range.Text
arrText = Split(strText, vbTab)
intIndex = Ubound(arrText)
strDate = arrText(intIndex)
strDate = Replace(strDate, "/", "")
intLength = Len(strDate)
strDate = Left(strDate, intlength - 1)
strFileName = "C:\Scripts\" & strUserName & " " & strDate & ".doc"
objWord.Quit
Wscript.Sleep 5000
Set objFSO = CreateObject("Scripting.FileSystemObject")
objFSO.MoveFile "C:\Scripts\Test.doc", strFileName
Prawdę mówiąc, okazał się on trochę bardziej skomplikowany, niż myślałem na początku. A to z powodu sposobu formatowania akapitów w programie Word. Oczywiście fakt, że ten skrypt jest trochę bardziej skomplikowany, może wynikać z tego – i zapewne tak jest – że nie do końca wiem, co robię i dzisiejszy artykuł nie jest tu żadnym wyjątkiem. Ale Wy się już pewnie do tego przyzwyczailiście, nieprawdaż?
Skrypt zaczyna się od utworzenia wystąpienia obiektu Word.Application i ustawienia wartości jego właściwości Visible na True; dzięki temu mamy działające wystąpienie programu Word, widoczne na ekranie. Następnie stosujemy poniższy wiersz kodu w celu otwarcia dokumentu, o który nam chodzi (C:\Scripts\Test.doc):
Set objDoc = objWord.Documents.Open("C:\Scripts\Test.doc")
Ten dokument (i wszystkie inne dokumenty programu Word w tym folderze) zaczynają się w ten sam sposób. Pierwsze dwa wiersze w każdym dokumencie wyglądają mniej więcej tak:
Person Name Ken Myer
EncounterDate 01/01/08
Czy to dobrze? Jasne, że tak. Oznacza to, że możemy pobrać nazwę użytkownika, wczytując właściwość Text pierwszego akapitu w dokumencie. Czyli po prostu pobieramy nazwę użytkownika, wykonując poniższy wiersz kodu:
strText = objDoc.Paragraphs(1).Range.Text
To także w pewnym sensie jest po naszej myśli. Problem polega tylko na tym, że nie mamy wyłącznie nazwy użytkownika, ale także następującą wartość:
Person Name Ken Myer
Ktoś wspominał o zbyt wielu informacjach? Chcąc zmienić nazwę pliku, chcemy żeby nazwa użytkownika wyglądała następująco:
Myer, Ken
Co to wszystko oznacza? A to mianowicie, że przed nami jeszcze sporo pracy.
Według TG, mamy dwa znaki tabulatora oddzielające Person Name od Ken Myer (imię i nazwisko osoby). Mając to na uwadze, możemy użyć funkcji Split w celu zamiany tej wartości ciągu na tablicę, używając znaku tabulatora (reprezentowanego przez stałą vbTab w skrypcie VBScript) jako delimitera:
arrText = Split(strText, vbTab)
W ten sposób otrzymamy tablicę wyglądającą następująco, w której gwiazdka reprezentuje znak tabulatora:
Person Name
Ken Myer
Jak widzimy, nazwa użytkownika to ostatni element w tablicy. Jak możemy pobrać tę wartość? Cóż, na początek używamy poniższego wiersza kodu oraz funkcji UBound w celu określenia numeru indeksu ostatniego elementu w tablicy:
intIndex = Ubound(arrText)
Teraz możemy zastosować ten oto wiersz kodu do pobrania nazwy użytkownika i zachowania jej w zmiennej o nazwie strUserName:
strUserName = arrText(intIndex)
Pomału zaczynamy dochodzić do sedna. Teraz musimy znaleźć sposób na przeformatowanie tej nazwy (czyli zamianę ciągu Ken Myer na Myer Ken). W tym celu tworzymy jeszcze jedną tablicę, tym razem rozdzielając zmienną strUserName i używając jako delimitera spacji pomiędzy Ken a Myer:
arrUserName = Split(strUserName, " ")
Otrzymujemy nową tablicę, w której element 0 to Ken, a element 1 to Myer.
Teraz napotykamy na pewien problem. Co prawda nie taki, jak dwóch kolesi próbujących odebrać emeryturę zmarłego kolegi, ale zawsze problem. Ponieważ nazwisko użytkownika pojawia się na końcu wiersza, ma dołączony znak końca akapitu; to oznacza, że element 1 w tablicy wygląda następująco, z gwiazdką reprezentującą znak końca akapitu:
Myer*
Jeżeli chcemy otrzymać wynik, który da się odczytać, musimy pozbyć się tego ostatniego znaku. (Zaufajcie mi, inaczej się nie da.) Jednym prostym sposobem pozbycia się tego znaku jest zastosowanie funkcji Len w celu określenia całkowitej liczby znaków w ciągu:
intLength = Len(arrUserName(1))
Kiedy nam się uda, możemy zastosować funkcję Left w celu pobrania wszystkich znaków w ciągu, z wyjątkiem ostatniego (długość ciągu minus 1). Robimy to w ten oto sposób:
strName = Left(arrUserName(1), intlength - 1)
Teraz możemy w końcu przeformatować nazwę użytkownika za pomocą poniższego wiersza kodu, zachowując wartość w zmiennej o nazwie strUserName:
strUserName = strName & ", " & arrUserName(0)
To nam załatwia sprawę wiersza nr 1 w dokumencie programu Word. W przypadku wiersza 2 stosujemy podobne podejście, tym razem pobierając Text drugiego akapitu w pliku:
strText = objDoc.Paragraphs(2).Range.Text
Po oddzieleniu części dotyczącej daty używamy poniższego wiersza kodu w celu usunięcia wszystkich znaków „/” w dacie:
strDate = Replace(strDate, "/", "")
Uwaga. Po co to robimy? Właśnie: ponieważ nie możemy użyć znaku / w nazwie pliku.
Teraz stosujemy te oto dwa wiersze kodu, w celu usunięcia znaku końca akapitu z naszej daty:
intLength = Len(strDate)
strDate = Left(strDate, intlength - 1)
Nadążacie? To dobrze. Zobaczmy, co już mamy. Mamy teraz zmienną (strUserName) o następującej wartości:
Myer, Ken
Mamy także drugą zmienną (strDate) o poniższej wartości:
010108
Teraz, kiedy mamy te dwa elementy, możemy utworzyć nową ścieżkę pliku za pomocą tego wiersza kodu:
strFileName = "C:\Scripts\" & strUserName & " " & strDate & ".doc"
Dzięki temu otrzymamy zmienną strFileName równą:
C:\Scripts\Myer, Ken 010108.doc
I właśnie o taką wartość nam chodziło.
W tym momencie dokument programu Word nie jest nam już potrzebny; wywołujemy zatem metodę Quit w celu zakończenia działania programu Microsoft Word:
objWord.Quit
Następnie wykonujemy poniższy wiersz kodu w celu zatrzymania skryptu na pięć sekund:
Wscript.Sleep 5000
Po co zatrzymujemy skrypt? No cóż, jeżeli zamkniemy program Word i od razu spróbujemy zmienić nazwę pliku, otrzymamy komunikat o błędzie odmowy dostępu; tak się stanie, jeżeli działanie programu Word nie całkiem się zakończyło i jeszcze blokuje plik. Zatrzymanie skryptu na pięć sekund daje programowi Word wystarczająco dużo czasu na zamknięcie przed próbą zmiany nazwy pliku.
A skoro już o tym mowa, te oto dwa wiersze kodu zmieniają nazwę pliku:
Set objFSO = CreateObject("Scripting.FileSystemObject")
objFSO.MoveFile "C:\Scripts\Test.doc", strFileName
Jak widzimy, ta część skryptu nie jest w ogóle skomplikowana. Tworzymy tutaj tylko wystąpienie obiektu Scripting.FileSystemObject i używamy metody MoveFile w celu zmiany nazwy pliku:
Ważne: |
---|
Uwaga:OK, może i nie jest skomplikowana, ale trochę dezorientująca. Z jakiegoś powodu obiekt FileSystemObject nie posiada metody Rename; wymaga natomiast „przeniesienia” pliku z jednej ścieżki do drugiej. Jeżeli jednak te ścieżki znajdują się w tym samym folderze, nazwy plików zostaną skutecznie zmienione.(Sami spróbujcie, a zobaczycie, że mam rację.). |
Tak przy okazji, powinienem także zaznaczyć, że niniejszy skrypt działa wyłącznie na komputerze lokalnym. Czy mógłby działać na plikach znajdujących się na zdalnym komputerze? Tak, ale używanie programu Word z plikami znajdującymi się na zdalnym komputerze jest trochę trudne. Ale co tam: jeżeli naprawdę będziecie tego chcieli, to zobaczę, co się da zrobić.
To jest tak naprawdę bardzo przyjemny skrypt, z jednym małym wyjątkiem: chodziło nam o to, żeby uruchomić ten skrypt dla wszystkich plików znajdujących się w folderze. Żaden problem. Skoro już macie podstawowe wiadomości na temat tego, co nasz skrypt robi i jak to robi, mogę pokazać Wam skrypt w wersji dla-wszystkich-plików-w-folderze bez żadnych dodatkowych wyjaśnień. Miłej zabawy!
No tak, byłbym zapomniał:
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFolder = objFSO.GetFolder("C:\Temp")
Set objWord = CreateObject("Word.Application")objWord.Visible = True
For Each objFile in objFolder.Files
Set objDoc = objWord.Documents.Open(objFile.Path)
strText = objDoc.Paragraphs(1).Range.Text
arrText = Split(strText, vbTab)
intIndex = Ubound(arrText)
strUserName = arrText(intIndex)
arrUserName = Split(strUserName, " ")
intLength = Len(arrUserName(1))
strName = Left(arrUserName(1), intlength - 1)
strUserName = strName & ", " & arrUserName(0)
strText = objDoc.Paragraphs(2).Range.Text
arrText = Split(strText, vbTab)
intIndex = Ubound(arrText)
strDate = arrText(intIndex)
strDate = Replace(strDate, "/", "")
intLength = Len(strDate)
strDate = Left(strDate, intlength - 1)
strFileName = "C:\Temp\" & strUserName & " " & strDate & ".doc"
objDoc.Close
Wscript.Sleep 2000
Set objFSO = CreateObject("Scripting.FileSystemObject")
objFSO.MoveFile objFile.Path, strFileName
Next
objWord.Quit
To nam załatwia całą sprawę. Mam nadzieję, że wszystko jest zrozumiałe. Jakby co, wiecie, gdzie mnie znaleźć.
Do początku strony |