2016-01-22 15 views
5

Załóżmy, że chcemy dodać jakiś tekst na końcu dokumentu i od razu dostęp go jako Range obiektu, dzięki czemu można ustawić pewne właściwości nim bez wpływając powyższy tekst . Idealnie, metoda zwraca obiekt Range, który byłby idealny do tego, ale tak nie jest.funkcja MS Word, aby dołączyć zakres do dokumentu

To mnie denerwuje, że Słowo musi wiedzieć doskonale, jaki zakres określa wynik wywołania InsertAfter, ale na pierwszy rzut oka muszę go obliczyć "po fakcie" od długości wstawionego tekstu, lub w niektórych inny sposób.

Więc wymyśliłem proste podejście do pracy. W pseudo-kodzie (w rzeczywistości jest to Delphi kod ale mam nadzieję, że nie zniechęci odpowiedzi VBA), co mogę zrobić, to ten

ARange := Document.Range 
ARange.Text := 'AAA' 

AEnd := ARange.End - 1  // AEnd is an integer 
ARange.SetRange(AEnd, AEnd) 
ARange.Text := 'XXX' 
ARange.Bold := True 

i wydaje się, że mogę kontynuować w nieskończoność, dodając bloki tekstu do końca dokumentu przez powtórzenie drugiego bloku kodu.

Linia

ARange.SetRange(AEnd, AEnd) 

jak rozumiem, wydaje się skonstruować nową serię na końcu istniejącego (w przeciwieństwie do wywoływania Collapse na istniejącej gamy), i działa dobrze dla prostych przypadków testowych Próbowałem. Ale zastanawiam się, czy nie mam gdzieś jakiejś sztuczki. Czy istnieje bardziej bezpośredni sposób dołączenia zakresu do dokumentu i uzyskania odniesienia do niego?

PS: Powinienem był być nieco jaśniejszy, próbuję to zrobić bez użycia obiektu Selection (z różnych powodów, w tym z faktu, że można mieć tylko jedną z nich w danej chwili).

+0

Dzięki @KenWhite. Powinienem wspomnieć, że starałem się unikać selekcji ze względu na niedawną wypowiedź Cindy Meister (która wydaje się być specjalistką i ekspertem w dziedzinie programu Word). – MartynA

Odpowiedz

3

Istnieje wiele sposobów na uzyskanie zakresu na końcu dokumentu. Odkryłeś jednego, ale jak mówisz, jest to trochę okrężne. Moje preferencje:

Word.Range rngEndOfDoc = Document.Content; 
//Content returns a Range object and is a property, not a method like Range() 
rngEndOfDoc.Collapse(Word.WdCollapseDirection.wdCollapseEnd); 
rngEndOfDoc.Text = "Text at the end of the document"; 

Collapsing zakres jest koncepcyjnie jak naciśnięcie w prawo (lub w lewo) klawisz strzałki, gdy masz wybór. Tak więc rngEndOfDoc staje się "punktem", a nie zawiera całą treść głównej części dokumentu.

FWIW Nigdy nie mogę wymyślić sytuacji, w której użyłbym do tego EndKey (emulacja działań użytkownika) i zmieniam tylko wybór, gdy chcę zostawić użytkownika na końcu dokumentu, aby mógł on zacznij pisać w tej lokalizacji.

+0

Podczas pracy w Delphi automatyzuje sam dokument.Użytkownik nie jest obecny; nie jest to makro VBA, które będzie uruchamiane przez użytkownika z poziomu programu Word. Przesuwanie zaznaczenia w dokumentach tworzonych programowo jest w porządku, a używanie narzędzia EndKey jest w porządku. –

+2

@KenWhite. Niezupełnie, nie, nie jest. Po pierwsze, nie jest tak efektywny jak praca z Zasięgiem. Nawet jeśli użytkownik nie wchodzi w interakcję z dokumentem, program Word musi zmienić miejsce, w którym znajduje się kursor w dokumencie. A jeśli okno dokumentu nie jest widoczne, wybór może być trudny, ponieważ program Word polega na "fizycznym" układaniu strony dla pewnych rzeczy. Wybór jest z natury nieprzewidywalny, chociaż przyznaję w przypadku EndKey'a aktualną Historię, prawdopodobnie skończysz tam, gdzie się spodziewasz. Ale jeśli istnieją alternatywy do korzystania z selekcji, powinieneś tego unikać, gdy tylko jest to możliwe. –

+0

To twoje preferencje. Korzystanie z selekcji jest łatwe i wystarczająco szybkie dla większości potrzeb. Używam go do automatyzacji generowania niektórych dokumentów i jest wystarczająco wydajny dla moich potrzeb. Jeśli masz inne preferencje, to twój wybór; nie czyni to źle. –

2

Pomyśl o Document.Range jako związku wszystkich możliwych zakresów w dokumencie głównym (tj. Oprócz nagłówków, stopek, rzeczy pływających itp.). Zawsze zaczyna się przed pierwszą postacią i kończy po ostatniej postaci (która, jak się okazuje, jest zawsze ukrytym znaczkiem akapitu). Nie jest możliwe zdefiniowanie innego zakresu, który jest po bieżącym Document.Range lub, konceptualnie "dołącz" cokolwiek po Document.Range, ponieważ nie ma "po" Document.Range (zawsze dociera do końca).

Tak więc, aby rozszerzyć dokument o nowy tekst lub inne wstawiane obiekty, należy wstawić je na końcu Document.Range - w rzeczywistości tuż przed końcem, ponieważ ostatni, ukryty znak akapitu musi nadal być ostateczną postacią dokumentu. To właśnie robisz w swoim pseudokod. w VBA, pusta zakres na końcu dokumentu można się odwoływać z

Document.Range(Document.Range.End-1, Document.Range.End-1) 

Próbując zdefiniować go w Document.Range.End faktycznie podnosi błąd, gdyż wskazuje po tej ostatniej (ukryty) charakter - i to jest z Dokumentu - dlatego potrzebujemy "-1".

Po uzyskaniu tego zakresu możemy wypełnić go materiałem - rozwijając go i logicznie, Document.Range.Na przykład, aby dodać tekst na koniec bieżącego dokumentu, można by napisać

ActiveDocument.Range(ActiveDocument.Range.End-1, ActiveDocument.Range.End-1).Text = "New Text" 

Zauważ, że ta sama „ostateczne” pusty zakres można dojechać z:

Document.Bookmarks("\EndOfDoc").Range 
+1

Dzięki: "ponieważ nie ma" po "the Document.Range". Tak, dobry punkt, +1. "Próba zdefiniowania go w Document.Range.End": Dziwne, ponieważ działa dla mnie, pozwól mi spróbować. End - 1 w moim kodzie ... – MartynA

+1

Och, mam to ... To dlatego, że używasz 'Range. SetRange'. Ta metoda automatycznie przestawia wartość swoich parametrów na "Range.End - 1" i nie generuje żadnego błędu. Jeśli wykonasz "ARange.SetRange AEnd + 100, AEnd + 100", to nadal ustawisz swój zakres - cicho - na (AEnd-1, AEnd-1) - i ukryjesz fakt, że wskazałeś na nieprawidłową pozycję. Natomiast 'Document.Range' spowoduje błąd. – dnep

+0

Aha, niezły chwyt1. Czy mógłbyś wyjaśnić dokładnie, co rozumiesz przez "The Document.Range z drugiej strony"? To znaczy. jaki kod dokładnie rzuci błąd, o którym wspomniałeś. – MartynA

0

następujące prace dla mnie w Word 15 (Office 365) przy użyciu biblioteki typów Word 2010 (używam wczesnego wiązania, ale powinno działać tak samo z późnym wiązaniem). Word to TWordApplication, a aRange to WordRange.

Word.Selection.EndKey(wdStory, wdMove); 
aRange := Word.Selection.Range; 
aRange.Text := 'This is new text added at the end.'; 
3

Dziękując za trzy godne podziwu odpowiedzi od innych, pomyślałem, że dodam moją własną . Poniżej przedstawiono dwie wersje funkcji, które zacząłem, pragnąc, aby Word dostarczył natywnie , zwracając dołączony zakres.

Pierwsza wersja wykorzystuje obiekty MS Word w MS Word Type Library importowej jednostki, która tradycyjnie pochodzi z Delphi (np Word2000.Pas jeden) i wykorzystuje „wczesne wiązanie” automatyzację natomiast druga wersja robi to samo z późnym wiązaniem.

function AppendRange(InputRange : Range) : Range; 
var 
    Direction : OleVariant; 
begin 
    Result := InputRange; 
    Direction := wdCollapseEnd; 
    Result.Collapse(Direction); 
end; 

function AppendRangeLB(InputRange : OleVariant) : OleVariant; 
begin 
    Result := InputRange; 
    Result.Collapse(wdCollapseEnd); 
end; 

Użycie to np.

AppendedRange := AppendRange(ExistingRange); 
AppendedRange.Text := 'YYY'; 
+0

Wiesz, to byłby cenny wkład sam w sobie. StackOverflow pozwala zamieścić pytanie i odpowiedzieć na nie, jako wkład w koncepcję Q & A witryny. Może bardziej sensownym jest zadać konkretne pytanie i zamieścić powyższą odpowiedź jako odpowiedź :-) –

+0

@CindyMeister: Dzięki za to, choć trochę się denerwuję, że odpowiadanie na własne pytania jest nieco jak mówienie o sobie jako o pierwszym znaku ... Poważnie, może jednak spróbuję z nieco bardziej wyrafinowaną wersją mojej odpowiedzi używając (jeśli uda mi się ją uruchomić, co będzie ciekawym małym projektem w sobie) funkcja językowa dodana do Delphi a zaraz po niej. Zapytam, czy/kiedy to zrobisz. – MartynA

Powiązane problemy