Centrum Skryptów - Microsoft Office

Jak wyodrębnić określone informacje z dokumentu programu Word, a następnie wykorzystać je w celu zmiany nazwy dokumentu?

Udostępnij na: Facebook

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 Do początku strony

Centrum Skryptów - Microsoft Office