Konu: Word Dosyasına Bilgi Yazmak
Mevcut olan bir .doc dosyam var. 4 sayfadan oluşuyor. Bu sayfalardaki boşluklara bilgi yazmak istiyorum. İstediğim sayfanın satır ve sutununa nasıl bilgi yazabilirim?
Giriş yapmadınız. Lütfen giriş yapın yada kayıt olun.
fox4um » Microsoft Office Otomasyonu » Word Dosyasına Bilgi Yazmak
Mevcut olan bir .doc dosyam var. 4 sayfadan oluşuyor. Bu sayfalardaki boşluklara bilgi yazmak istiyorum. İstediğim sayfanın satır ve sutununa nasıl bilgi yazabilirim?
Biraz muglak bir soru olmus. Istedigim sayfa ve satir darken sayfa ve satir nolari biliyor musunuz? Biliyorsaniz, Selection.Move() ile gider yazarsiniz.
Bilmiyorsaniz, onu bulmak icin bir kriter kullaniyor olmaniz lazim.
Isin kolayi, eger dokuman uzerinde sizin kontrolunuz var ise Bookmark ya da DocumentVariable kullanmak. O zaman dogrudan Bookmark'a gider yazarsiniz, ya da DocumentVariable degerini kurarsiniz. Ornek:
#include wdconstants.h
#Define NL Chr(13)+Chr(10)
*** set the LOCALEID to English
nlLocaleId=Sys(3004) && Save local id
=Sys(3006,1033) && We will be sending instructions in English
Use employee && test table
oWordDocument=Createobject("word.application") && Create word object
With oWordDocument
.Documents.Add && Create a new doc
.Visible = .T.
.Activate
Scan
.Selection.TypeText('Employee Info Start.'+NL)
.Selection.TypeText(Transform(emp_id)+NL+First_Name-(' '+Last_Name)+NL)
.Selection.Collapse(wdCollapseEnd)
lnRangeStart = .Selection.Range.End && set range for notes text and bookmark
.Selection.TypeText(Nvl(notes,'')+NL+NL)
lnRangeEnd = .Selection.Range.End
.Activedocument.Bookmarks.Add('b'+Padl(Recno(),2,'0'),.Activedocument.Range(lnRangeStart,lnRangeEnd))
Endscan
firstBmkName = .Activedocument.Bookmarks(1).Name
.Activedocument.Bookmarks(1).Select
Messagebox('first bookmark selected',4096,'',3000)
.Selection.Collapse(wdCollapseEnd)
.Selection.Expand( wdParagraph )
Messagebox('Deleting para after first bookmark',4096,'',3000)
.Selection.Delete
.Selection.TypeText( 'Para deleted' + NL )
If .Activedocument.Bookmarks.Exists(firstBmkName)
.Activedocument.Bookmarks(firstBmkName).Select
.Selection.Font.Color = 0xFF
Endif
Endwith
**** Set the LocaleId to the previous value
=Sys(3006,Val(nlLocaleId))
Çetin bey haklısınız.
Sorumu biraz açarak tekrarlıyorum
2 sayfadan oluşan Belge.doc adında bir dosyam var.
1. sayfanın 12.satırının 25 karakterinden veya sütunundan başlamak üzere "Adı" yazılsın.
2.sayfanın 5.satırının 50.kaarekterinden veya sütunundan başlamak üzere "Soyadı" yazılsın.
Bu iki olayı gerçekleştiren bir kod yazabilir misiniz?
#include wdconstants.h
Local oWord as "word.application"
oWord=Createobject("word.application") && Create word object
With oWord
.Documents.Open("d:\Temp\GoToTest.docx")
.Visible = .T.
.Activate
.Selection.GoTo(wdGoToPage, wdGoToNext, ,"1")
.Selection.MoveDown(wdLine, 12-1)
.Selection.MoveRight(wdCharacter, 25-1)
.Selection.TypeText("Adi")
.Selection.GoTo(wdGoToPage, wdGoToNext, ,"2")
.Selection.MoveDown(wdLine, 5-1)
.Selection.MoveRight(wdCharacter, 50-1)
.Selection.TypeText("Soyadi")
endwith
Ama daha once soyledigim gibi bookmark ya da variable kullanmak daha iyi. Boyle karakterle filan, birisi en ufak degisiklik yaptiginda kayar.
Word dosyası sabit. Bir sözleşme dosyası. Standart maddeler.
O zaman icinde bookmark kullanmak daha kolay. Bir orneginde istediginiz yerlere bookmark koyup template olarak saklayin. Sonra yenii dokumani o template bazli acip bookmarka gidip istediginiz yazarsiniz:)
#include "wdcons.h"
Local oWord as "Word.Application"
oWord = CREATEOBJECT("Word.Application")
With oWord
.visible = .t.
.Documents.Add("c:\templates\mytemplate.dotx")
With .ActiveDocument
lcBookmark1 = "Adi"
lcBookmark2 = "Soyadi"
If .Bookmarks.Exists(m.lcBookmark1)
.Range(.Bookmarks(m.lcBookmarkName1).Range.Start, .Bookmarks(m.lcBookmarkName1).Range.End).TypeText("Adi")
endif
If .Bookmarks.Exists(m.lcBookmark2)
.Range(.Bookmarks(m.lcBookmarkName2).Range.Start, .Bookmarks(m.lcBookmarkName2).Range.End).TypeText("Soyadi")
endif
Endwith
EndWith
Bu daha saglam bir yol.
"wdcons.h" dosyasını bulamadım. Nereden indirebilirim?
Çetin Bey,
http://www.denbil.com/Sozlesme.doc dosya burada.
1.sayfadaki adı soyadı karşısına
ve
2. sayfanın sağ alt kısımdaki personel bölümüne aynı isim yazılacak.
Ben maalesef başarılı olamadım.
Once wdconstants.h yi anlatayim. Bunun icin bir sey indirmenize gerek yok. Kendiniz olusturabilirsiniz.
1) Command windowda:
Modify Command wdconstants.h[enter]
ile yeni bir kod penceresin acin. Kenarda dursun.
2) Toolbardan ya da menuden Tools\Object Browser i acin.
3) Object Browser'da en soldaki ikonu clickleyin, COM tabindaki listede icinde Word geceni arayin (adi makineye kurulmus versiyonlara gore degisebiliyor:
Microsoft Word ...
Microsoft Office Word ...
Microsoft.Office.Interop.Word 12.0 ...
gibi. Bulunca secip kapatin. Ilk pencereye "Word" gelmis olmasi lazim.
4) Word nodunu genisletin. "Constants" goreceksiniz. Onu daha once actiginiz kod penceresine surukleyip birakin (surukleme ilk denemede calismayabiliyor). Oraya bir suru #DEFINE yazildigini goreceksiniz. Saklayip kapatin. Artik elinizde wdcontants.h var.
Not: Burada wdconstants.h gerekmiyor. #DEFINE'lari dogrudan icine ekledim.
Sozlesme.doc'u gorup ne istediginizi daha iyi anlayinca, sanirim bookmark ya da variable yerine (aslinda o da variable) Mail MergeField kullanmak daha iyi diye dusundum.
Once sizin .doc dosyasini actim ve dediginiz her iki yere de:
Insert\Field\MergeField dedim ve field adini AdiSoyadi yaptim. (Insert altinda Quick Parts\Field). Sonra da dosyayi template dosyasi olarak sakladim (doc word 97-2003 dosyasiydi, word 97-2003 template olarak Sozlesme.dot diye sakladim). Template dosyasinin kopyasini asagidaki adresten alabilirsiniz:
http://www.medikosoft.com/cetin/Sozlesme.dot
Sozlesme.dot dosyasi bende d:\temp\SerafettinMentes adli bir dizinde. Asagida ornek olarak bir dizi AdSoyad icin Sozlesmeler.doc adinda dosya olusturan kod var. Kod template dosyayi aciyor, tablodaki her kayit icin yeni bir "section" olacak sekilde Sozlesmeler.doc dosyasini yaratiyor. Arada cursor ve copy to kullandigim icin de, isim bitince ornek tablo siliniyor. Hali hazirda olan bir tablodan gelecektir buyuk ihtimalle, o zaman silmeden biraz ayarla onu kullanirsiniz (ya da cursor'a select edip bu sekilde silerek kullanirsiniz, nasil isterseniz). Bir de, wdSendToDocument yerine wdSendToPrinter gibi secenekler ile dogrudan printer'a gonderebilirsiniz, onu yaparsaniz, Quit demeden once BackgroundPrintStatus kontrolu yapin, yazim bitti mi diye.
Local lcTemplate, lcSaveAs, lcDataSource
lcTemplate = "D:\temp\SerafettinMentes\Sozlesme.dot"
lcSaveAs = "D:\temp\SerafettinMentes\Sozlesmeler.doc"
lcDataSource = Forcepath(Sys(2015)+'.dbf', Sys(2023))
Create Cursor sozlesmeler (SozlesmeID i Autoinc Nextvalue 1, AdiSoyadi v(100))
Insert Into sozlesmeler (AdiSoyadi) Values ('Serafettin Mentes')
Insert Into sozlesmeler (AdiSoyadi) Values ('Cetin Basoz')
Insert Into sozlesmeler (AdiSoyadi) Values ('Mehmet En')
Insert Into sozlesmeler (AdiSoyadi) Values ('Ali Buyuk')
Insert Into sozlesmeler (AdiSoyadi) Values ('Mustafa Sari')
Insert Into sozlesmeler (AdiSoyadi) Values ('Huseyin Lacivert')
Copy To (m.lcDataSource)
MergeToDoc(m.lcDataSource, m.lcTemplate, m.lcSaveAs)
** Erase Temp table
Erase (m.lcDataSource)
Procedure MergeToDoc
Lparameters tcDataSource, tcTemplate, tcSaveAs
Wait Window Nowait "Creating Word Document.Please wait..."
#Define wdOpenFormatAuto 0
#Define wdSendToNewDocument 0
#Define wdSendToPrinter 1
#Define wdSendToEmail 2
#Define wdSendToFax 3
#Define wdAlertsNone 0
#Define wdDoNotSaveChanges 0
#DEFINE wdFormatDocument97 0
Local lcConnection, lcSource, lcSQLStatement, loDoc
m.lcSource = Forcepath('myDummy.udl',Sys(2023))
If !File(m.lcSource)
Strtofile('',m.lcSource)
Endif
lcConnection = 'Provider=VFPOLEDB;Data source='+Justpath(m.tcDataSource)
lcSQLStatement = Textmerge('select * from [<< JustStem(m.tcdatasource) >>]')
*** set the LOCALEID to English
nlLocaleId=Sys(3004) && Save local id
=Sys(3006,1033) && We will be sending instructions in English
*** set the LOCALEID to English
oWordDocument=Createobject("word.application") && Create word object
With oWordDocument
loDoc = .documents.Add(m.tcTemplate) && Open a template
With .ActiveDocument.Mailmerge
.OpenDataSource(m.lcSource, wdOpenFormatAuto,.F.,,.T.,,,,,,,m.lcConnection, m.lcSQLStatement)
.EditMainDocument && Activate the main document
.Destination = wdSendToNewDocument
.Execute()
Endwith
m.loDoc.Close(0) && closing the template doc - keep open to create your own template
loDoc = null
.ActiveDocument.SaveAs(m.tcSaveAs, wdFormatDocument97)
.ActiveDocument.Saved = .T.
.DisplayAlerts = wdAlertsNone
.NormalTemplate.Saved = .T.
For Each oDoc In .documents
oDoc.Close(wdDoNotSaveChanges)
Endfor
oDoc = .Null.
.Quit(wdDoNotSaveChanges)
Endwith
**** Set the LocaleId to the previous value
=Sys(3006,Val(nlLocaleId))
Wait clear
Endproc
biraz basit ve pratik bilgi olacak profesyonel degil ama iş görürü sanırım
d:\Sozlesme.doc
sablon dosyan olsun bunun içine personelin adının yazılacagı yere %m_peradi% yazarsan işini görö gibi
m_personel="CİN ALİ GEL "
DELETE FILE GETENV("UserProfile")+"\Desktop\Sozlesme.doc"
COPY FILE "d:\Sozlesme.doc " TO GETENV("UserProfile")+"\Desktop\Sozlesme.doc"
m_dosya=GETENV("UserProfile")+"\Desktop\Sozlesme.doc"
Local oWord As Word.Application
oWord = CreateObject("Word.Application")
With oWord As WORD.Application
.Documents.Open(m_dosya)
.Visible = .T.
With .Selection.Find
.Text = "%m_peradi%"
.Replacement.Text = &m_personel
.Execute(,,,,,,,,,,2,,,,)
ENDWITH
EndWith
oWord = .Null.
&m_personel
derken:
m.m_personel
demek istedin sanirim:)
Herkese teşekkür ederim.
Sayın anteplinin önerisini internetten ararken buldum ve uyguladım.
Local oWord As "Word.Application"
oWord = CreateObject("Word.Application")
oDoc = oWord.Documents.Open("D:\Sozlesme.doc")
oRange = oWord.ActiveDocument.Content
With oRange.Find
.Text = "Adı Soyadı :"
.Replacement.Text = "Adı Soyadı :"+Alltrim(personel.adi_soyadi)
.Execute( , , , , , , , , , , 2)
EndWith
oWord.Visible = .T.
Neden oyle yapmamalisin onu da dusundunuz umarim:) Bul ve degistirin sakincalarini da hesaba katin.
Neden oyle yapmamalisin onu da dusundunuz umarim:) Bul ve degistirin sakincalarini da hesaba katin.
Abicim kafam takıldı şimdi. Bende üç aşağı beş yukarı Antepli arkadaşın yaptığı gibi yapmıştım zamanında. Ve o zamandan beri sorunsuz bir şekilde çalışıyor. Acaba nasıl sakıncalar olabilir ki ?
Benim yaptığımda, word dökümanı içinde datadan gelen bilgileri koyacağım yere <yzAdSoyad>, <yzAdres> vb.. gibi taglar koymuştum. Ve sonrasında da
lcDeger[yzAdSoyad] = Alltrim(thisform.txtAdUnvan.Value)
lcDeger[yzAdres] = Alltrim(thisform.edtAdres.Value)
DO while oSel.Find.Execute('\<*\>',,,.T.,,,.T.,1,,)
lcFoundText=oWord.SELECTION.TEXT
lcField = Substr(lcFoundText,2,Len(lcFoundText)-2)
oWord.Selection.Find.Execute('\<'+lcField+'\>',,,,,,,,,lcDeger[&lcField])
EndDo
tarzında bir kodlama vardı. Sonuçta <> tag işaretleri arasında benim koyduğum değişken isimleri dışında word dökümanı içinde geçen başka bir bilgi olmadığına göre sadece bunları bulup, replace etmesi gerekmez mi ?
cetinbasoz yazdı:Neden oyle yapmamalisin onu da dusundunuz umarim:) Bul ve degistirin sakincalarini da hesaba katin.
Abicim kafam takıldı şimdi. Bende üç aşağı beş yukarı Antepli arkadaşın yaptığı gibi yapmıştım zamanında. Ve o zamandan beri sorunsuz bir şekilde çalışıyor. Acaba nasıl sakıncalar olabilir ki ?
Benim yaptığımda, word dökümanı içinde datadan gelen bilgileri koyacağım yere <yzAdSoyad>, <yzAdres> vb.. gibi taglar koymuştum. Ve sonrasında da
lcDeger[yzAdSoyad] = Alltrim(thisform.txtAdUnvan.Value) lcDeger[yzAdres] = Alltrim(thisform.edtAdres.Value) DO while oSel.Find.Execute('\<*\>',,,.T.,,,.T.,1,,) lcFoundText=oWord.SELECTION.TEXT lcField = Substr(lcFoundText,2,Len(lcFoundText)-2) oWord.Selection.Find.Execute('\<'+lcField+'\>',,,,,,,,,lcDeger[&lcField]) EndDo
tarzında bir kodlama vardı. Sonuçta <> tag işaretleri arasında benim koyduğum değişken isimleri dışında word dökümanı içinde geçen başka bir bilgi olmadığına göre sadece bunları bulup, replace etmesi gerekmez mi ?
Canim kardesim, sen buralara ugrar miydin
Sen "tag" kullanmissin, duz metin degil, ondan avantajlisin. Ancak Find, "story" basina calisir. Eger bu taglari header, footer vs. gibi storylere alirsan o zaman calismayacak, hepsini dolasip update etmen gerekiyor. Bir de madem < > tag kullaniyorsun, o taglarin merge gibi bir fazlasi (chevron) zaten mailmerge field demek << >>. Yani sen dolayli olarak mergefield'i kesfetmissin Bir de su var, Find gibi cozumler tek bir dokuman icin. Oysa mailmerge, bir tek tablodan ayni anda N tane dokumani "merge" etmek icin. Yani 100 tane personelin de olsa, 1000 tane de olsa calistirdigin tek bir mailmerge. Ayni sablonu word kayit basina 'merge' ediyor, Ne bileyim, bizim yaptiklarimiz icinde en saglikli calisan bu oldu.
fox4um » Microsoft Office Otomasyonu » Word Dosyasına Bilgi Yazmak