文章列表
 
您正在查看 "Word" 分类下的文章

2008-04-04 15:39

将对话框映射到 Word 对象模型

以下脚本中引用的选项对应于“选项”对话框的“视图”选项卡中的选项。要在 Microsoft Word 2003 中访问这些选项,请依次单击“工具”、“选项”和“视图”选项卡。下面显示了此对话框中的可用选项与 Microsoft Word 对象模型之间的映射。如果看不清图形(很可能会出现这种情况),请单击此处查看大图。

视图

已使用 Microsoft Word 2003 对本页中显示的脚本进行了测试。至少某些功能可以在任何支持 Visual Basic for Applications (VBA) 的 Microsoft Word 版本上使用;不过,没有使用任何其他版本对这些脚本进行测试。

用于检索值的示例代码

示例脚本检索 Microsoft Word 2003“选项”对话框的“视图”选项卡中的配置信息。

On Error Resume Next
Set objWord = CreateObject("Word.Application")
Set objOptions = objWord.Options
Set objDoc = objWord.Documents.Add()
Set objWindow = objWord.ActiveDocument.ActiveWindow
Set objView = objWord.ActiveDocument.ActiveWindow.View
Set objComments = objDoc.Comments

Wscript.Echo "Startup Task Pane: " & objWord.ShowStartupDialog
Wscript.Echo "Status bar: " & objWord.DisplayStatusBar
Wscript.Echo "Windows in Taskbar: " & _
    objWord.ShowWindowsInTaskbar
Wscript.Echo "Highlight: " & objView.ShowHighlight
Wscript.Echo "Bookmarks: " & objView.ShowBookmarks
Wscript.Echo "Tab characters: " & objView.ShowTabs
Wscript.Echo "Spaces: " & objView.ShowSpaces
Wscript.Echo "Paragraph marks: " & objView.ShowParagraphs
Wscript.Echo "Drawings: " & objView.ShowDrawings
Wscript.Echo "Object anchors: " & objView.ShowObjectAnchors
Wscript.Echo "Text boundaries: " & objView.ShowTextBoundaries
Wscript.Echo "Wrap to window: " & objView.WrapToWindow
Wscript.Echo "Animated text: " & objView.ShowAnimation
Wscript.Echo "Smart tags: " & objView.DisplaySmartTags
Wscript.Echo "Picture placeholders: " & _
    objView.ShowPicturePlaceholders
Wscript.Echo "All: " & objView.ShowAll
Wscript.Echo "Field codes: " & objView.ShowFieldCodes
Wscript.Echo "Hidden text: " & objView.ShowHiddenText
Wscript.Echo "Optional hyphens: " & objView.ShowHyphens
Wscript.Echo "Background colors and images: " & _
    objView.DisplayBackgrounds
Wscript.Echo "Field shading: " & objView.FieldShading
For Each strComment in objComments
    Wscript.Echo "Screen tips: " & strComment.ShowTip
Next
Wscript.Echo "Horizontal scroll bar: " & _
    objWindow.DisplayHorizontalScrollBar
Wscript.Echo "Vertical scroll bar: " & _
    objWindow.DisplayVerticalScrollBar
Wscript.Echo "Vertical ruler: " & _
    objWindow.DisplayVerticalRuler

objWord.Quit

用于修改值的示例代码

示例脚本将 Microsoft Word 中的“启动任务窗格”选项设置为 TRUE。

On Error Resume Next

Set objWord = CreateObject("Word.Application")
objWord.ShowStartupDialog = TRUE

objWord.Quit

这些示例脚本不受任何 Microsoft 标准支持计划或服务的支持。这里仅按原样提供示例脚本,而不作任何类型的担保。Microsoft 进一步明确拒绝所有的暗示担保,包括但不限于对适销性或对特定目的适用性的任何暗示担保。使用或执行示例脚本和文档所引起的全部风险应由您自己承担。在任何情况下,对于使用或不能使用示例脚本或文档所引起的任何损害(包括但不限于商业利润损失、业务中断、商业信息丢失或其他资金损失所造成的损害),Microsoft、其作者以及参与脚本创建、生产或传递的任何其他人员都概不负责,即使 Microsoft 已被告知存在这些损害的可能性。


 
2008-04-01 18:09

如果您的组织使用 XML 架构 (XML 架构:以 XML 编写的正式规范,定义了 XML 文档的结构,包括元素名和丰富的数据类型,以及哪些元素要以组合形式出现,每一元素具有哪些属性。)定义数据结构,则本文中描述的过程是最佳方法。在 Microsoft Office Word 2007 中,通过将架构附加到文档,可以创建标准格式的 XML 文档,此类文档可包含自定义 XML 以及 Word XML 架构 (WordprocessingML) 所提供的格式和属性。

这种双架构用法不仅保留自定义架构定义的数据,而且还保留 WordprocessingML 定义的多种格式。或者,您也可以放弃 WordprocessingML,只保存您标记的内容(自定义 XML 数据)。

您要做什么?


将 XML 架构附加到文档

附加到文档中的 XML 架构是为您的组织进行自定义而设计的。XML 架构通常由 IT 专业人员创建,他们的职责就是在 Word 中为您的组织构建专用的模板或解决方案。

可用于附加到文档的架构在架构库中列出。

向架构库中添加架构

若要向架构库中添加架构,请按照下列步骤操作:

  1. “开发工具”选项卡上的“XML”组中,单击“架构”

    注释    若要显示“开发工具”选项卡,请执行下列操作: 单击“Office 按钮”按钮图像,然后单击“Word 选项”。 单击“常用”,然后在“使用 Word 时采用的首选项”下选中“在功能区显示‘开发工具’选项卡”复选框。(功能区是 Microsoft Office Fluent 用户界面的一个组件。)

  2. 单击“添加架构”,通过浏览找到要添加到架构库中的 XML 架构,然后单击“打开”
  3. “架构设置”对话框中,选择所需的选项,然后在“别名”框中为该架构键入名称。

    注释    您在此处键入的别名将显示在“模板和加载项”对话框的可用架构列表中。

  4. 单击“确定”

将架构附加到文档

在架构库中放置架构后,就可以将其附加到文档。

注释    可以将多个架构附加到文档。所有附加架构中的元素均显示在“XML 结构”任务窗格的元素列表中。

  1. 在 Word 中打开文档。
  2. “开发工具”选项卡上的“XML”组中,单击“架构”
  3. “当前已经附加了选中的架构”框中,选中要附加到文档的各 XML 架构的对应复选框。

返回页首 返回页首

将 XML 标记应用于文档内容

自定义 XML 架构附加到文档后,“XML 结构”任务窗格即会提供该架构中定义的元素列表。通过选择文档内容,然后从该列表中选择元素,即可将 XML 标记应用于文档中。如果架构为元素定义了属性,还可以在“XML 结构”任务窗格中指定这些属性。

添加或删除 XML 标记

请执行下列操作之一:

添加 XML 标记

  1. 在文档中,突出显示要添加标记的内容。

    可以在文档中选择字词、短语、段落、单元格、行、列、域、图片或对象。

  2. “XML 结构”任务窗格的“选择一种元素并应用于当前的选定内容”列表中,选择一种元素。

    注释    要对所选的元素和属性加以限制,请选中“仅列出当前元素的子元素”复选框。

  3. 如果需要,可为元素指定属性。

    显示 操作方法

    1. “XML 结构”任务窗格的“文档中的元素”下,右键单击相应的元素,然后单击“属性”
    2. “有效的属性”列表中,选择所需的属性。
    3. “值”框中,键入属性值。
    4. 单击“添加”

删除 XML 标记

  1. “XML 结构”任务窗格中,选中“在文档中显示 XML 标记”复选框。
  2. 在文档中,将指针停留在元素名的开始”元素名的结尾”标记上。
  3. 右键单击,然后单击“删除元素名标记,以删除该标记但不删除该标记的内容。

    注释    每个元素都有一个开始标记和结束标记。这两个标记只能成对删除。

显示或隐藏 XML 标记

  • 按 Ctrl+Shift+X。

打印 XML 标记

  1. 单击“Office 按钮”按钮图像,然后单击“Word 选项”
  2. 单击“高级”
  3. “打印”下,选中“打印 XML 标记”复选框。

显示 XML 元素名

如果文档包含空的 XML 元素,即使“在文档中显示 XML 标记”选项关闭,也可以在文档的主体中按名称查看这些元素。

  1. “开发工具”选项卡上的“XML”组中,单击“架构”
  2. 单击“XML 选项”
  3. “XML 视图选项”部分中,选中“显示用于所有空白元素的占位符文本”复选框。

提示    您可以为元素指定自己的占位符文本,方法是:右键单击相应的标记,单击“属性”,然后在“占位符文本”框中键入所需的文本。

防止意外删除 XML 元素

如果您希望用户能够编辑 XML 文档中的数据,但不能编辑或删除 XML 标记,可以使用文档保护功能使用户只能编辑 XML 元素的内容,而不能编辑标记本身。

  1. “XML 结构”任务窗格中,选中“在文档中显示 XML 标记”复选框。
  2. “开发工具”选项卡上的“保护”组中,单击“保护文档”
  3. “保护文档”任务窗格中,选中“仅允许在文档中进行此类编辑”复选框,然后选择“不允许任何更改(只读)”
  4. 在文档中,选择某一元素的内容。
  5. “保护文档”任务窗格中,选中“例外项(可选)”部分中的“每个人”复选框。
  6. 对希望用户编辑其内容的每个 XML 标记,分别重复步骤 4 和 5。
  7. 单击“是,启动强制保护”
  8. 请执行下列操作之一:
    • 若要指定密码以防无意中去除文档保护,请在“新密码(可选)”框中键入一个密码,然后确认该密码。
    • 若要对文档加密,以便只有经过验证的文档所有者才能去除保护,请单击“用户验证”

返回页首 返回页首

验证 XML 数据

Word 可以根据附加到 XML 文档的 XML 架构的规则,验证该文档。架构冲突显示在“XML 结构”任务窗格中,它们也显示在文档中。

提示    若要在应用 XML 标记时避免出现验证错误,请选中“XML 结构”任务窗格中的“仅列出当前元素的子元素”复选框。

  1. “开发工具”选项卡上的“XML”组中,单击“架构”
  2. “架构验证选项”下,执行下列一项或两项操作:
    • 若要强制执行验证,请选中“使用附加架构验证文档”复选框。
    • 若要防止 Word 保存无效的文档,请清除“允许另存为 XML (即使无效)”复选框。
  3. 当您在文档中工作时,请使用“XML 结构”任务窗格检查文档的有效性。在每个元素旁都会显示一个图标,用于指示该元素是否无效以及冲突的特性。此外,架构冲突在文档中还标有波浪线。

关闭波浪线

默认情况下,架构冲突在文档主体中标有波浪线。若要关闭此功能,请执行下列操作:

  1. “开发工具”选项卡上的“XML”组中,单击“架构”
  2. 单击“XML 选项”
  3. “架构验证选项”下,选中“隐藏文档中的架构冲突”复选框。

返回页首 返回页首

将 Word 格式和属性与自定义 XML 数据一起保存

如果要保留 Word 文档的页面布局和格式以及自定义 XML 数据,请使用以下过程保存文档。

  1. 单击“Office 按钮”按钮图像,然后单击“另存为”。.
  2. “保存类型”框中,单击“Word 2003 XML 文档”
  3. “文件名”框中,键入相应文档的名称。
  4. 如果要使用可扩展的样式表语言转换 (XSLT) (XSL 转换 (XSLT):一种文件,用于将 XML 文档转换为其他类型的文档,例如 HTML 或 XML。设计本意是作为 XSL 的一部分使用。) 设置文档的格式,请选中“应用转换”复选框,然后单击“转换”以找到 XSLT 文件。

    注意    如果在保存文件时应用 XSLT,Word 会丢弃 XSLT 未使用的所有数据。

  5. 单击“保存”

返回页首 返回页首

仅保存自定义 XML 数据

在仅保存自定义 XML 数据时,在生成的 XML 文件中将丢弃文档中未用附加架构中的元素标记的所有内容。

  1. 单击“Office 按钮”按钮图像,然后单击“另存为”。.
  2. “保存类型”框中,单击“Word 2003 XML 文档”
  3. “文件名”框中,键入相应文档的名称。
  4. 选中“仅保存数据”复选框。
  5. 如果要使用可扩展的样式表语言转换 (XSLT) (XSL 转换 (XSLT):一种文件,用于将 XML 文档转换为其他类型的文档,例如 HTML 或 XML。设计本意是作为 XSL 的一部分使用。) 设置文档的格式,请选中“应用转换”复选框,然后单击“转换”以找到 XSLT 文件。

    注意    如果在保存文件时应用 XSLT,Word 会丢弃 XSLT 未使用的所有数据。

  6. 单击“保存”
 
2008-03-12 10:04
When you force a new line in Word (whether by using ASCII 11 or ASCII 13) this does count as an additional character in the document, yes. Even though it's not as ".NET correct", for this reason you might want to use the C# escape codes instead of Environment.NewLine. \r is the equivalent of ASCII 13 = new paragraph. Right off-hand I can't remember what the equivalent of ASCII 11 is = new line (Word-specific).

Or, you'd need to rebuild your procedure to use the other approach. Here's an untested example, off the top of my head, of how using a single range would work:

String text1 = "The first text.";

String text2 = "Some more text ";

String text3 = "A third set of text.";

Word.Range rng = theDoc.Content;

//I want to start at the top of the document = start of the range

object oCollapseStart = Word.WdCollapseDirection.wdCollapseStart;

//I need to continue after a range

object oCollapseEnd = Word.WdCollapseDirection.wdCollapseEnd;

rng.Collapse(ref oCollapseStart);

rng.Text = text1;

rng.InsertParagraph();

rng.Collapse(ref oCollapseEnd);

rng.Text = text2;

rng.Collapse(ref oCollapseEnd);

Word.Field fld = rng.Fields.Add(rng //other args);

rng = fld.Result;

//Insert the rest of the text in a new line, after the field

rng.InsertParagraph;

rng.Collapse(ref oCollapseEnd);

rng.Text = text3;

Hi Again Cathy,

Working with multiple ranges worked like a charm!! (Sorry about the typo).

When I try to add a similar block of text later in the creation process (after the user has added 2-3 pages of text), they insertion of the hyperlink is "off" by a few characters. Does the inclusion the "Environment.NewLine" affect the calculation of a range? It appears that the number of these affects the placement of the hyperlink by that many characters.

Here's the code:

string

legEndText = Environment.NewLine + "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" + Environment.NewLine +"Join or leave the AGENDA mailing list via the Web page: " + Environment.NewLine;string newEndText1 = Environment.NewLine + Environment.NewLine + "For assistance with joining and leaving, All subscribers " + Environment.NewLine +"please call (555) 555-5500. CRS subscribers please call (555) 555-5500. " + Environment.NewLine + Environment.NewLine +Environment.NewLine + "For information on the action Agenda, to order Products or to provide " + Environment.NewLine +"feedback, please call John Doe at (555) 555-5500. " + Environment.NewLine + Environment.NewLine +"To order our Products, please call (555) 555-5500. ";

// since we're at the end of the document we need to get the range

for the text up to the start of "newEndText"

// then, add the hypStart to set the starting point for the hyperlink

Word.

object startDoc = 0;object endDoc;Range fullRange = legAlert.Range(ref startDoc, ref missing);// leaving out the end of the range, will get the end of the document's range

endDoc = fullRange.End;

// the length of the doc up to where we enter the remaining standard text

// programmatically set the range for the hyperlink

// the above strings can also be established in an app.config file and

// be obtained on the fly

hypStart = legEndText.Length + fullRange.End - 4;

hypEnd = legEndText.Length + fullRange.End - 3 + theLink.Length;

//   Here's where it gets a little weird, the hyperlink is set to the right "area", except for a few characters.

// So it appears that I have to subtract from the fullRange.End in order to set the hyperlink to the correct range.

// is this because of the Environment.NewLine ?

(As you can tell I'm new to this.)   Is the issue the number of Environment.NewLine's?  

Thanks again,

Paul

Mmm. Working with the Start and End points of a range is only reliable if you can be absolutely sure you aren't dealing with hidden text of fields. Fields are what Word uses to manage any dynamic content; page numbers are an obvious example. A field consists of the field code (which you can see by using Alt+F9 to toggle field codes on/off) and the field result. When you start counting characters in a selection or range, if a field is involved you'll get "strange" results. I avoid defining a range by using the Start and End properties if any other alternative is possible.

Inserting a Hyperlink inserts a Hyperlink field. It's not clear from your code snippet where randStart and randEnd come from; I'm assuming a typo in what you posted, but that doesn't seem to be an issue...

What I'd do in your place is either to work with multiple ranges, or to insert text-field-text so that I can continue "forwards" using the same range. Building on your approach, I'd make this small change:

// The point at which to insert the hyperlink

Word.Range rngHyp = newAlert.Range(

ref randStart, ref randEnd);

newAlert.Hyperlinks.Add(rngHyp,

report.Select();

Thanks that got me most of the way there. However, after doing the above the cursor, while no longer at the top of the doc is now in the middle of the last sentence.

Here's the code:

string

theLink = "http://www.crs.gov/products/flooraction/subscribe-crs-alert.shtml";object oAddress = theLink;// for setting the range of the hyperlink

// we want to collapse the range to the insertion point for the next text

// standard text

string startText = "See this week's Alert: Our items at "; // theLink goes herestring nextText = " for full text of the following reports." + Environment.NewLine + Environment.NewLine +"The following selected reports focus on key policy issues or some of the key issues involved that may receive action during the week of " + DateTime.Now.Date.ToString("dddd dd MMMM") + " " + DateTime.Now.Date.Year.ToString() + "." + Environment.NewLine;

hypStart = startText.Length;

hypEnd = startText.Length + theLink.Length;

testVSTO.

// set the insertion point to the top of the page

Word.

report.Text = startText + theLink +

// The point at which to insert the hyperlink

report = newAlert.Range(

ref randStart, ref randEnd);

newAlert.Hyperlinks.Add(report,

ref oAddress, ref missing, ref missing, ref missing, ref missing);

report.Collapse(ref collapseEnd);

report.Select();

_______________________________

That is, the last two line of code above leave the cursor at the end of the hyperlink or at hypEnd.

If I use this code:

report.SetRange(newAlert.Characters.Count, newAlert.Characters.Count);

instead of the

report.Collapse(ref collapseEnd);

the cursor is in the middle of the last sentence (eg: nextText).

Thanks again for any assistance,

Paul

Range report = newAlert.Range(ref missing, ref missing);" " + nextText + "\r";

ThisDocument newAlert = testVSTO.Globals.ThisDocument;

object collapseEnd = Word.WdCollapseDirection.wdCollapseEnd;

object hypStart ;object hypEnd ;
ref oAddress, ref missing, ref missing, ref missing, ref missing);//Now the range "report" doesn't changereport.Collapse(ref collapseEnd);

 
2008-03-11 21:58

参阅word帮助中的selection对象中的information 属性说明,先取出要填充的位置,以便以后按指定位置填充:

information 属性


返回有关指定的所选内容或区域的信息。variant 类型,只读。

语法

expression.information(type)

expression 必需。该表达式返回一个 range 或 selection 对象。

type long 类型,必需。需要返回的信息。可取下列 wdinformation 常量之一:

wdactiveendadjustedpagenumber 返回页码,在该页中包含指定的所选内容或区域的活动结尾。如果设置了一个起始页码,并对页码进行了手工调整,则返回调整过的页码。


wdactiveendpagenumber 返回页码,在该页中包含指定的所选内容或区域的活动结尾,页码从文档的开头开始计算而不考虑对页码的任何手工调整。


wdactiveendsectionnumber 返回节号,在该节中包含了指定的所选内容或区域的活动结尾。


wdatendofrowmarker 如果指定的所选内容或区域位于表格的行结尾标记处,则本参数返回 true。


wdcapslock 如果大写字母锁定模式有效,则本参数返回 true。


wdendofrangecolumnnumber 返回表格列号,在该表格列中包含了指定的所选内容或区域的活动结尾。


wdendofrangerownumber 返回表格行号,在该表格行包含了指定的所选内容或区域的活动结尾。


wdfirstcharactercolumnnumber 返回指定的所选内容或区域中第一个字符的位置。如果所选内容或区域是折叠的,则返回所选内容或区域右侧紧接着的字符编号。


wdfirstcharacterlinenumber 返回所选内容中第一个字符的行号。如果 pagination 属性为 false,或 draft 属性为 true,则返回 - 1。


wdframeisselected 如果所选内容或区域是一个完整的图文框文本框,则本参数返回 true。


wdheaderfootertype 返回一个值,该值表明包含了指定的所选内容或区域的页眉或页脚的类型,如下表所示。 值 页眉或页脚的类型
- 1 无
0 偶数页页眉
1 奇数页页眉
2 偶数页页脚
3 奇数页页脚
4 第一个页眉
5 第一个页脚


wdhorizontalpositionrelativetopage 返回指定的所选内容或区域的水平位置。该位置是所选内容或区域的左边与页面的左边之间的距离,以磅为单位。如果所选内容或区域不可见,则返回 - 1。


wdhorizontalpositionrelativetotextboundary 返回指定的所选内容或区域相对于周围最近的正文边界的左边的水平位置,以磅为单位。如果所选内容或区域没有显示在当前屏幕,则本参数返回 - 1。


wdinclipboard 有关此常量的详细内容,请参阅 microsoft office 98 macintosh 版的语言参考帮助。


wdincommentpane 如果指定的所选内容或区域位于批注窗格,则返回 true。


wdinendnote 如果指定的所选内容或区域位于页面视图的尾注区内,或者位于普通视图的尾注窗格中,则本参数返回 true。


wdinfootnote 如果指定的所选内容或区域位于页面视图的脚注区内,或者位于普通视图的脚注窗格中,则本参数返回 true。


wdinfootnoteendnotepane 如果指定的所选内容或区域位于页面视图的脚注或尾注区内,或者位于普通视图的脚注或尾注窗格中,则本参数返回 true。详细内容,请参阅前面的 wdinfootnote 和 wdinendnote 的说明。


wdinheaderfooter 如果指定的所选内容或区域位于页眉或页脚窗格中,或者位于页面视图的页眉或页脚中,则本参数返回 true。


wdinmasterdocument 如果指定的所选内容或区域位于主控文档中,则本参数返回 true。
wdinwordmail 返回一个值,该值表明了所选内容或区域的的位置,如下表所示。值 位置
0 所选内容或区域不在一条电子邮件消息中。
1 所选内容或区域位于正在发送的电子邮件中。
2 所选内容或区域位于正在阅读的电子邮件中。


wdmaximumnumberofcolumns 返回所选内容或区域中任何行的最大表格列数。


wdmaximumnumberofrows 返回指定的所选内容或区域中表格的最大行数。


wdnumberofpagesindocument 返回与所选内容或区域相关联的文档的页数。


wdnumlock 如果 num lock 有效,则本参数返回 true。


wdovertype 如果改写模式有效,则本参数返回 true。可用 overtype 属性改变改写模式的状态。


wdreferenceoftype 返回一个值,该值表明所选内容相对于脚注、尾注或批注引用的位置,如下表所示。 值 描述
— 1 所选内容或区域包含、但不只限定于脚注、尾注或批注引用中。
0 所选内容或区域不在脚注、尾注或批注引用之前。
1 所选内容或区域位于脚注引用之前。
2 所选内容或区域位于尾注引用之前。
3 所选内容或区域位于批注引用之前。


wdrevisionmarking 如果修订功能处于活动状态,则本参数返回 true。


wdselectionmode 返回一个值,该值表明当前的选定模式,如下表所示。 值 选定模式
0 常规选定
1 扩展选定
2 列选定


wdstartofrangecolumnnumber 返回所选内容或区域的起点所在的表格的列号。


wdstartofrangerownumber 返回所选内容或区域的起点所在的表格的行号。


wdverticalpositionrelativetopage 返回所选内容或区域的垂直位置,即所选内容的上边与页面的上边之间的距离,以磅为单位。如果所选内容或区域没有显示在屏幕上,则本参数返回 - 1。


wdverticalpositionrelativetotextboundary 返回所选内容或区域相对于周围最近的正文边界的上边的垂直位置,以磅为单位。如果所选内容或区域没有显示在屏幕上,则本参数返回 - 1。


wdwithintable 如果所选内容位于一个表格中,则本参数返回 true。


wdzoompercentage 返回由 percentage 属性设置的当前的放大百分比。

 
2008-03-11 21:36

在Word中怎么样通过编写程序实时检测光标位置?我没有办法做到,因为Thisdocument对象只提供NEW,CLOSE,OPEN三种事件,不知各位大虾有没有其他办法?谢谢了 问题点数:20、回复次数:4Top

1 楼MagicFan(我爱杨过) 回复于 2002-04-01 11:35:26 得分 20

写一个Class Module,在这个class里面定义一个WithEvent的application。然后用它的WindowSelectionChange的事件。
例如:
写一个Class Module名为aaa.
Public WithEvents App As Application

Private Sub App_WindowSelectionChange(ByVal sel As Selection)
'在这里面可以写你的代码,对selection位置的不同,作你想作的事。
End Sub

然后定义一个Module名为testaaa
Dim AppEvents As New EDD
Sub InitEvents() '必须要在Document加载的时候触发这个事件,WindowSelectionChange才会有效。
Set AppEvents.App = Application
End Sub

最后,在Document_New或者Document_Open里面
InitEvents

好了,大功告成。

Top

2 楼MagicFan(我爱杨过) 回复于 2002-04-01 11:36:56 得分 0

sorry,刚刚写错一个词。

然后定义一个Module名为testaaa
Dim AppEvents As New EDD

应该是
然后定义一个Module名为testaaa
Dim AppEvents As New aaa

 
2008-03-10 22:04

从文档中移除保护功能。

命名空间:Microsoft.Office.Tools.Word
程序集:Microsoft.Office.Tools.Word(在 microsoft.office.tools.word.dll 中)

Collapse 图像语法

Visual Basic(声明)
Public Overridable Sub Unprotect ( _
 <OptionalAttribute> ByRef Password As Object _
)
Visual Basic(用法)
Dim instance As Document
Dim Password As Object

instance.Unprotect(Password)
C#
public virtual void Unprotect (
 [OptionalAttribute] ref Object Password
)

参数

Password

要用来保护文档的密码。密码区分大小写。如果文档是用密码保护的,但是所提供的密码不正确,则会出现一个对话框,提示用户输入密码。

Collapse 图像备注

应避免在应用程序中使用硬编码的密码。如果在某个过程中需要使用密码,则向用户请求该密码并将其存储到一个变量中,然后在您的代码中使用该变量。

如果文档不受保护,则将引发异常。

可选参数

有关可选参数的信息,请参见了解 COM Interop 中的可选参数

Collapse 图像示例

下面的代码示例使用 Unprotect 方法从文档中移除保护功能。该示例假定密码变量 securelyStoredPassword 是从用户输入获取的。

Visual Basic CopyCode image复制代码
Private Sub DocumentUnprotect(ByRef securelyStoredPassword As Object)
    If Me.ProtectionType <> Word.WdProtectionType.wdNoProtection Then
        Me.Unprotect(securelyStoredPassword)
    End If
End Sub
C# CopyCode image复制代码
private void DocumentUnprotect(ref object securelyStoredPassword)
{
    if (this.ProtectionType != Word.WdProtectionType.wdNoProtection)
    {
        this.Unprotect(ref securelyStoredPassword);
    }
 
2008-03-09 12:06
=========================================
作者:howwa@sina.com
时间:2007-3-1
=========================================
在WORD中如何用VBA宏语言选定一行、一段,删除一行、一段,移动光标至行首、行尾、段首、段尾等。请看以下内容。
Sub MoveToCurrentLineStart()
    '移动光标至当前行首
    Selection.HomeKey unit:=wdLine
End Sub
Sub MoveToCurrentLineEnd()
    '移动光标至当前行尾
    Selection.EndKey unit:=wdLine
End Sub
Sub SelectToCurrentLineStart()
    '选择从光标至当前行首的内容
    Selection.HomeKey unit:=wdLine, Extend:=wdExtend
End Sub
Sub SelectToCurrentLineEnd()
    '选择从光标至当前行尾的内容
    Selection.EndKey unit:=wdLine, Extend:=wdExtend
End Sub
Sub SelectCurrentLine()
    '选择当前行
    Selection.HomeKey unit:=wdLine
    Selection.EndKey unit:=wdLine, Extend:=wdExtend
End Sub
Sub MoveToDocStart()
    '移动光标至文档开始
    Selection.HomeKey unit:=wdStory
End Sub
Sub MoveToDocEnd()
    '移动光标至文档结尾
    Selection.EndKey unit:=wdStory
End Sub
Sub SelectToDocStart()
    '选择从光标至文档开始的内容
    Selection.HomeKey unit:=wdStory, Extend:=wdExtend
End Sub
Sub SelectToDocEnd()
    '选择从光标至文档结尾的内容
    Selection.EndKey unit:=wdStory, Extend:=wdExtend
End Sub
Sub SelectDocAll()
    '选择文档全部内容(从WholeStory可猜出Story应是当前文档的意思)
    Selection.WholeStory
End Sub
Sub MoveToCurrentParagraphStart()
    '移动光标至当前段落的开始
    Selection.MoveUp unit:=wdParagraph
End Sub
Sub MoveToCurrentParagraphEnd()
    '移动光标至当前段落的结尾
    Selection.MoveDown unit:=wdParagraph
End Sub
Sub SelectToCurrentParagraphStart()
    '选择从光标至当前段落开始的内容
    Selection.MoveUp unit:=wdParagraph, Extend:=wdExtend
End Sub
Sub SelectToCurrentParagraphEnd()
    '选择从光标至当前段落结尾的内容
    Selection.MoveDown unit:=wdParagraph, Extend:=wdExtend
End Sub
Sub SelectCurrentParagraph()
    '选择光标所在段落的内容
    Selection.MoveUp unit:=wdParagraph
    Selection.MoveDown unit:=wdParagraph, Extend:=wdExtend
End Sub
Sub DisplaySelectionStartAndEnd()
    '显示选择区的开始与结束的位置,注意:文档第1个字符的位置是0
    MsgBox ("第" & Selection.Start & "个字符至第" & Selection.End & "个字符")
End Sub
Sub DeleteCurrentLine()
    '删除当前行
    Selection.HomeKey unit:=wdLine
    Selection.EndKey unit:=wdLine, Extend:=wdExtend
    Selection.Delete
End Sub
Sub DeleteCurrentParagraph()
    '删除当前段落
    Selection.MoveUp unit:=wdParagraph
    Selection.MoveDown unit:=wdParagraph, Extend:=wdExtend
    Selection.Delete
End Sub
 
2008-03-06 17:44
Microsoft Office Word 2003 对象模型中新增的 XML 功能
发布日期 : 10/21/2004 | 更新日期 : 10/21/2004

Peter Vogel
PH&V Information Services

适用于:
Microsoft® Office Word 2003

摘要: 使用 Microsoft Office Word 2003 对象模型中的新增 XML 功能借助代码来操作文件。与其他的方法相比,通过 Word 的基于 XML 的功能,您可以利用 XSLT 的能力将文档内容转换为所需的任何格式。您可以将这些转换应用到文档的单个部分以从纯文本创建邮件标签,或者将这些转换作为整体应用到文档以便将电子邮件转换为销售订单。

本页内容

使用 XML 使用 XML
访问文档 访问文档
转换文本 转换文本
小结 小结

使用 XML

在 Microsoft® Office Word 2003 中使用文档的 XML 表示包括两种不同的情况:

  • 通过从架构中添加元素和属性,可以加载 XML 架构并创建文档。作为该种情况的示例,您可能要加载 Docbook 架构(用于创建关于硬件和软件的文档的开放式规范)。 1 显示已加载 Docbook 架构的 Word 2003。

  • 您可以像以前那样使用 Word 2003。还可以选择让代码作为以 WordML(本地 Word XML 格式)术语编写的 XML 文档的一部分与 Word 2003 文档协同工作。

在这两种情况中,您可以访问文档的 XML 表示来提供新增功能。

odc_wd2k3xmlom_fig01

1. Word 2003 中创建 XML 文档

加载架构

要使用 XML 架构,首要的步骤就是加载架构并将其与文档相关联。可以通过来自 Application 对象或 Document 对象的代码来添加架构。

在将架构添加到文档之前,请确保您使用的 Word 版本支持添加架构。Microsoft Office Professional Edition 2003 中的 Microsoft Office Word 2003 核心程序或 Microsoft Office Word 2003 都支持添加自定义架构。如果 Application 对象的 ArbitraryXMLSupportAvailable 属性设置为 True,那么 Word 2003 支持利用 XML 词汇而不是 WordML 来构建文档。

向应用程序对象添加架构

通过使用 XMLNamespaces 集合的 Add 方法,可以将架构添加到 Application 对象。添加后,这些架构可以通过 XML 任务窗格用于用户了。以下代码将 Docbook 架构添加到 Namespaces 集合,如果架构没有定义一个 (dcb),则指定与架构一起使用的命名空间,并且为 Word 2003 在其用户界面 (UI) 中使用的架构指定别名,在此例中,该名称为 Docbook

If Application. ArbitraryXMLSupportAvailable = True Then
Application.XMLNamespaces.Add "c:\Docbook.xsd", "dcb", "Docbook"
End If

添加后,架构由 XMLNamespaces 集合中的 XMLNamespace 对象表示。每个 XMLNamespace 都可以具有一个与它相关联的 XSLT 转换的集合。使用 XSLTransforms 集合的 Add 方法,可以将新的转换添加到 XMLNamespace,同时会创建一个 XMLTransform 对象。必须将包含 XSLT 转换的文件的路径传递到 Add 方法,并且作为可选方案,也可以传递 Word 2003 可以在其 UI 中使用的别名。该示例将 toc.xsl 转换添加到集合中,该集合将作为 Generate TOC 出现在 UI 中:

Application.XMLNamespaces(1).XSLTransforms.Add _
 "c:\transforms\toc.xsl",  "Generate TOC"

使用关联文档的架构

在将架构添加到 Application 对象的 XMLNamespaces 集合后,可以使用 XMLNamespace 对象的 AttachToDocument 方法将该架构与文档相关联。该代码将 XMLNamespaces 集合中的第二个架构与当前文档相关联:

Application.XMLNamespaces(2).AttachToDocument ActiveDocument

通过 Document 对象的 XMLSchemaReferences 集合,可以使用 XMLSchemaReferences 集合的 Add 方法将架构直接添加到文档。通过引用在将架构添加到 Application 对象的 XMLNamespaces 集合时建立的 NamespaceURI,该代码将 Docbook 架构添加到文档的架构引用:

ActiveDocument.XMLSchemaReferences.Add "dcb"

或者,可以不使用 XMLNamespaces 集合,而直接将架构添加到文档中。这也会将架构添加到 Application 对象的 XMLNamespaces 集合中:

ActiveDocument.XMLSchemaReferences.Add "dcb",  _
"Docbook",  "C:\shemas\Docbook.xsd"

XMLSchemaReference 对象的 Add 方法的第一个参数就是与架构一起使用的命名空间(在此例中,为 dcb)。第二个参数为 UI 中使用的架构提供一个别名。第三个参数是到要加载的架构的路径。

访问文档

有两种方法可以用于访问 Word 2003 中文档的 XML 表示:

  • 提取 XML 文本

  • 访问组成 XML 文档对象模型的 XML 节点

提取文本

Word 2003 文档始终由 WordML 标记组成。在 Word 2003 中使用架构时,架构的标记会与 WordML 标记相互混合。WordML 标记控制文档在 Word 2003 中的显示方式。

通过 RangeSelection 对象的 XML 属性,可以提取文档的 XML 文本。XML 属性始终返回完整的 WordML 文档,包括 WordML 根元素 (wordDocument)。例如,以下代码从活动文档的第二段中提取 XML:

ActiveDocument.Paragraphs(2).Range.XML

作为示例,该示例文本只包含两个短段落:

The quick brown fox jumps over the lazy dog.
A rolling stone gathers momentum.

提取第一段的 WordML 表示会返回很多文本 — 超过 3,000 个字符。XML 属性返回的文档非常大,因为它不仅包括选定范围的文本,还包括影响文本的所有上下文信息:文档中样式的定义、有关文档字体的信息、文档的页面尺寸和边距等等。

XML 属性返回的文档内,构成内容的段落都位于 WordML body元素内部。body 元素文档包含<t>标记(文本)、<r>标记(文本的运行)以及<p>标记(段落)中文档的内容。同时出现在正文中的<sectPr>标记保存着定义文档部分(例如页面尺寸和边距)的元素。

如果基于某些 XML 架构创建文档,那么组成该架构的标记将会与允许 Word 2003 操作文本的 WordML 标记相互混合。作为示例,这是 Docbook 文档的开始:

<book><title>Office MSXML</title></book>

检索该文档的 XML 属性会返回在其正文标记中带有如下代码的文档:

<w:body>
<wx:sect>
<ns0:book>
<w:p>
<ns0:title>
<w:r><w:t> Office MSXML</w:t></w:r>
</ns0:title>
</w:p>
</ns0:book>
. . .

要使 WordML 和 Docbook 标记分开,使用前缀 ns0 标记 Docbook 该前缀将这些标记限制在 wordDocument 元素上定义的Docbook 命名空间。

<w:wordDocument
xmlns:w="http://schemas.microsoft.com/office/word/2003/wordml"
. . .various other namespace declarations. . .
xmlns:ns0="dcb">

为了检索所用架构的元素,XML 属性会接受允许删除 WordML 标记的一个参数(称为 DataOnly)。当 DataOnly 设置为 True 时,以下代码只返回文档中的非 WordML XML 标记:

ActiveDocument.Paragraphs(1).Range.XML(True)

对于示例 Docbook 文档,返回的 XML 类似如下所示:

<?xml version="1.0" standalone="no"?>
<book xmlns="DocBook">
<title>Office MSXML</title>
</book>

提取 XML 节点

在利用架构创建的文档中,还可以使用 RangeSelectionDocument 对象的 XMLNodes 属性,将文档作为一系列 XML 节点进行访问。XMLNodes 集合包含 XMLNode 对象,如果您使用 MSXML 工具集中的 DOM 分析器,则该对象的方法和属性看起来会非常熟悉。该示例主要关注添加到 Word 2003 对象模型的 XMLNode 对象的功能,尽管 MSXML 的某些通用方法和属性对 Word 2003 开发人员也非常有用。

在前面显示的示例 Docbook 文档中有两个节点:一个用于 book 元素,一个用于 title 元素。以下代码会检索 title 元素:

Dim nd As XMLNode
Set nd = ActiveDocument.XMLNodes(2)

node 对象的属性包括节点的内容(文本)、节点的名称 (BaseName) 以及节点的命名空间 (NamespaceURI)。

在大多数情况下,只需要在文档中处理其中一些节点。Document 对象的 SelectNodes 方法使用 XPath 语句来指定节点,从而可以提取您想要的节点。当利用命名空间搜索元素时,必须将命名空间的前缀包括在标记名称中。SelectNodes 方法的第二个参数通过使用与 XML 文档中相同的语法来定义命名空间。不管嵌套的深度如何,该示例都会找到 Docbook 命名空间中该文档的所有 TITLE 元素,该命名空间将 ns0 作为其前缀:

Dim nds As XMLNodes
Dim nd As XMLNode
Set nds = ActiveDocument.SelectNodes("//ns0:title",  _
"xmlns:ns0='dcb' ")
For Each nd In nds
   MsgBox "Value for title tags: " & nd.Text
Next

XMLNodes 集合的第一个成员位于位置 1,因此这是使用 For. . .Next 循环处理所有成员的所要使用的代码:

For ing = 1 To nds.Count
    Set nd = nds.Item(ing)
    MsgBox "Value for title tags: " & nd.Text
Next

为了提高搜索的速度,可以将 SelectNodes 方法的第三个参数设置为 False,这样会导致搜索跳过所有文本节点(在 XML 元素的打开和关闭标记之间的文本内容)。如果您并不搜索节点的内容,同时文档包含很多文本(Word 2003 文档通常如此),那么设置这个参数可以显著提高搜索速度。

对于要添加到文档中的任何特定命名空间,可以通过 XMSchemaReference 对象的 NamespaceURI 属性检索命名空间。重新编写之前的代码以使用 NamespaceURI 属性,可得到如下代码:

Set nds = ActiveDocument.SelectNodes("//ns0:title", "xmlns:ns0=' " & _
ActiveDocument.XMLSchemaReferences(1).NamespaceURI  & _
"' ")

Word 2003 新增的基于 XML 的技术可以顺利地合并来自 Word 以前版本的 Word 对象。例如,检索到某个节点后,就可以通过检索 XMLNode 对象的 Range 属性,使用该节点表示的 Word 对象。

Dim rng As Range
Set rng = nd.Range

还可获得较大的 Word 2003 文档内有关节点位置的某些反馈。例如,节点的 Level 属性指示出节点是否为可显示的文本 (Level = wdXMLNodeLevelInline),或者为段落的一部分 (Level = wdXMLNodeLevelParagraph)。Level 属性还指示出节点是否为表格行或单元格的一部分。

更改文档

可以使用 InsertXML 方法或 XMLNodes 集合来更新文档。两种方法都允许操作文档的内容来创建新的资料。

更新文本

通过 RangeSelection 对象的 InsertXML 方法,可以利用插入 XML 文本的任意字符串来更新文档。如果更新没有使用架构的 WordML 文档,则必须插入完整的 WordML 文档。幸运的是,基本 WordML 文档包含五个标记(wordDocument、body、p、r、t)以及 WordML 命名空间。例如,该文档在最小的 WordML 文档中包含如下单个字符串:

<w:wordDocument xmlns:w=
'http://schemas.microsoft.com/office/word/2003/wordml'>
<w:body>
    <w:p>
<w:r>
<w:t>Hello, World.</w:t>
</w:r>
   </w:p>
</w:body>
</w:wordDocument>

作为示例,在以下文本中,我们假设选择了单词 jumps

The quick brown fox jumps over the lazy dog.

以下代码将当前选择 (jumps) 替换为单词 leaps

Selection.Range.InsertXML _
"<w:wordDocument xmlns:w=" & _
"'http://schemas.microsoft.com/office/word/2003/wordml'>" & _
"<w:body><w:p><w:r><w:t>leaps</w:t></w:r></w:p></w:body>" & _
"</w:wordDocument>"

更新节点

对于使用架构的文档,通过 XMLNode 对象的 Range 属性的 XML 属性,可以添加新的 XML。将新资料插入文档时,需要组合 WordML 标记(以便将文本显示在 Word 中)和架构的标记。然而,为了使代码更易读,接下来的示例忽略了 WordML 标记。

示例 Docbook 文档的标题为“Office XML”。对该 Docbook 文档的一个更改可以插入与 title 标记一起使用的 subtitle 标记,可以得到以下结构:

<?xml version="1.0" standalone="no"?>
<book xmlns="DocBook">
<title>Office MSXML<subtitle>XML Objects</subtitle></title>
</book>

插入 XML 时前缀是必需的,以便该标记会限制到正确的架构。要确保插入的 XML 正确地形成,必须在要插入的 XML 内定义前缀(及其命名空间)。以下代码将 subtitle 标记插入到文档:

ActiveDocument.XMLNodes(2).Range.InsertXML  _
"<ns0:subtitle xmlns:ns0='dcb'>XML Objects</ns0:subtitle>"

将 XML 插入到节点会替换该节点的所有现有内容。使用之前的代码将新内容插入到 title 节点中,以替换现有内容(如 2 所示):

<ns0:book>
<ns0:title>
<ns0:subtitle>XML Objects</ns0:subtitle>
</ns0:title>
</ns0:book>

odc_wd2k3xmlom_fig02

2. title 元素内容替换为 subtitle 元素

如果您的目标是添加到现有内容(而不是替换它),则必须向父节点添加一个子节点。使用节点的 ChildNodes 集合的 Add 方法,传递新节点所属的节点和命名空间的名称(Word 2003 会负责为该节点分配适当的前缀),您可以添加节点。以下示例会添加一个名为 subtitle 的子节点,作为 Docbook 命名空间的一部分。在创建该节点后,代码就会将字符串“XML Objects”分配给节点的 Text 属性:

Dim nd As XMLNode
Set nd = ActiveDocument.XMLNodes(2).ChildNodes.Add ("subtitle", _
"dcb")
nd.Text = "XML Objects"

生成的代码包含以下标记集(请参见 3):

<ns0:book>
<ns0:title>Office MSXML<ns0:subtitle>XML Objects</ns0:subtitle>
</ns0:title>
</ns0:book>

odc_wd2k3xmlom_fig03

3. subtitle 子元素添加到 title 元素

再次运行代码会在刚刚添加的子标题后添加另一个子标题。

添加子节点不会受到限制。使用 XMLNodes 集合的 Add 方法,可以在现有文档的任意位置添加节点。在何处添加节点取决于所用的对象类型。例如,如果使用 ActiveDocument 对象,如此例中所示,新节点将会被插入到光标位置:

ActiveDocument.XMLNodes.Add "subtitle", "dcb"

XMLNodes 集合也可以从任意节点的 Range 属性获得。由于是从文档中的现有节点中使用,添加新节点后,它会包括所有已经存在的子节点。例如,该文档会在 chapter 元素内嵌套一段文本。

<ns0:book xmlns:ns0='dcb'>
<ns0:chapter>My Paragraph</ns0:chapter>
</ns0:book>

要将段落节点添加到章节(并且将该段落文本放在新创建的段落中),可以使用以下带有章节的 Range 属性的代码:

Dim ndBook As XMLNode
Set nd = ActiveDocument.XMLNodes(1)
nd.Range.XMLNodes.Add "para", "dcb"

结果就是下面的 XML:

<ns0:book xmlns:ns0='dcb'>
<ns0:chapter>
<ns0:para>My Paragraph</ns0:para>
</ns0:chapter>
</ns0:book>

转换文本

InsertXML 方法的实际功能在于该方法的第二个参数,它接受到包含 XSLT 的文件的路径名称。传递路径名后,InsertXML 方法会使用文件中的 XSLT 代码在第一个参数中处理 XML,然后将结果插入到文档中。

例如,该 Docbook 文档包含两个 chapter 元素和一个称为 toc 的空目录元素(对于这些示例,会包括相关的 WordML 标记以确保在插入文本后,由 Word 2003 显示该文本):

<ns0:book>
   <ns0:toc/>
   <ns0:chapter>
      <ns0:title>
<w:p><w:r><w:t>Chapter 1</w:t></w:r></w:p>
</ns0:title>
   <ns0:chapter>
<ns0:chapter>
      <ns0:title>
<w:p><w:r><w:t>Chapter 2</w:t></w:r></w:p>
</ns0:title>
   <ns0:chapter>
</ns0:book>

以下 XSLT 会找到所有章节 title 标记,并生成包含 TOCENTRY 和 TITLE 标记的 Docbook 目录:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" 
xmlns:xsl='http://www.w3.org/1999/XSL/Transform'
xmlns:w='http://schemas.microsoft.com/office/word/2003/wordml'
xmlns:ns0='dcb'>

<xsl:template match="/">
<w:wordDocument>
<w:body>
   <xsl:for-each select="//ns0:chapter">
      <ns0:tocchap><ns0:tocentry>
      <w:p>
<w:r>
<w:t>
<xsl:value-of select="w:p/ns0:title"/>
</w:t>
</w:r>
</w:p>
      </ns0:tocentry></ns0:tocchap>
   </xsl:for-each>
</w:body>
</w:wordDocument>

</xsl:template>

</xsl:stylesheet>

在通过 InsertXML 方法完成的所有更新中,您必须插入完整的 wordDocument 文档,这样样式表也可以添加 wordDocument 和 BODY 元素。要求使用<WordML>、<p> 、<r> 和<t>标记,以便在 Word 2003 中显示 TOCENTRY 元素中的文本。

下一段代码会检索文档中到 TOC 节点的引用。然后,代码调用该节点的 InsertXML 方法,传递该文档的 XML 文本以及包含 XSLT 的文件的路径。

Dim ndToc As XMLNode
Set ndToc = ActiveDocument.SelectSingleNode("//ns0:toc", _
"xmlns:ns0='dcb')
ndToc.Range.InsertXML ActiveDocument.Range.XML, _
"c:/Transforms/toc.xsl"

结果是生成构建自文档中的 chapter 元素、带有目录的 Docbook 文档。

如果要转换整个文档,而不是转换选定节点的内容,您可以调用 Document 对象的 TransformDocument 方法。TransformDocument 方法接受两个参数:

  • 到带有 XSLT 代码的文件的路径

  • 指示是处理整个文档还是仅处理非 WordML 标记的布尔值。该参数设置为 True 会忽略 WordML 标记。

不需要对这些方法的调用中的路径进行硬编码,您就可以使用指定命名空间的 XSLTransforms 集合的 XSLTransform 对象。XSLTransform 对象的 Location 属性提供到包含 XSLT 的文件的路径名。如果重新编写前面的代码以使用 Location 属性,您将获得以下代码:

ndToc.Range.InsertXML ActiveDocument.Range.XML, _
Application.XMLNamespaces(1).XSLTransforms(1).Location

转换现有文档的内容只是应用 XSLT 的其中一种用法。您可以像阅读 XML 文档那样简单地使用 XSLT 就可以将文档转换为 WordML 格式(或其他任何 XML 格式)。例如,Microsoft Office Access 2003 支持以 XML 格式导出其表格。简单的 XSLT 转换允许文件格式转换为 WordML 以便作为 Word 2003 文档或者转换为 Docbook 格式,如果这种格式是该信息的最终格式。

响应更改

Word 2003 也会在执行 XML 操作时引发事件。Document 对象将引发两个新的、与 XML 相关的事件:

  • XMLAfterInsert:添加新节点时引发。该事件例程被传递到新节点的引用。

  • XMLBeforeDelete:删除节点时引发。一个到 Range 对象的引用会传递到该事件例程,该对象包括部分要删除的文档以及对要删除的节点的引用。

一个布尔变量会传递到两个事件,如果在撤消或重复操作过程中添加或删除节点,则将该变量设置为 True

Word 2003 Application 对象将激发两个新的、与 XML 相关的事件:

  • XMLValidationError:只要文档中出现验证错误就会引发。单个参数会被传递到该事件:到出错节点的引用。

  • XMLSelectionChange:只要选择新节点就引发。四个参数会传递到该事件例程:新选定资料的 WordSelection 对象、对失去焦点和获得焦点的节点的引用以及原因代码。

要使用这些事件,您需要设置全局变量并将它们分配给适当的对象。以下代码作为类模块的 Initialize 事件的一部分完成此操作:

Dim WithEvents wrd As Application
Dim WithEvents doc As Document
Private Sub Class_Initialize()
   Set doc = ActiveDocument
   Set wrd = Application
End Sub

在某些其他事件中,例如 Word 2003 中的 AutoOpen 例程,必须创建类模块。完成后,类模块中的代码可以捕获 XML 事件。

选择更改

您可以出于各种原因更改当前选择的节点:移动光标、插入新节点和删除节点。并不是所有这些活动都会生成选择更改事件。例如,您可以让光标位于一个子元素的 end 元素和另一个子元素的 start 元素之间。在这种情况下,当前选择的节点是两个子节点的父节点。如果在相同的父节点内的两个不同子节点之间单击,那么选定的节点不会更改并且不会触发任何选择更改事件。

如果确实引发了选择更改事件,那么作为最后一个参数传递到 XMLSelectionChange 事件的原因代码会指示出选择更改的原因。原因代码可具有三个值:

  • wdXMLSelectionChangeReasonMove:因为在文档中移动光标选择不同节点而导致选择发生变化。这时,在文档首次打开后,您首先选择一个节点,OldXMLNode 的属性为 Nothing

  • wdXMLSelectionChangeReasonDelete:因为节点被删除导致选择发生变化。OldXMLNode 始终为 Nothing。并不是所有删除都会引发选择更改。例如,如果当前选定的节点是父节点,删除子节点则不会生成选择更改事件。使用 XMLBeforeDelete 事件来捕获所有删除。

  • wdXMLSelectionChangeReasonInsert:因为插入新节点导致选择发生变化。新节点在 NewXMLNode 中传递。还可以使用 XMLAfterInsert 事件来捕获节点插入。

作为示例,当插入 TOC 元素时,以下代码会运行创建带有目录的代码:

Private Sub doc_XMLAfterInsert(ByVal NewXMLNode As XMLNode, _
ByVal InUndoRedo As Boolean)
If NewXMLNode.BaseName = "toc" Then
NewXMLNode.Range.InsertXML ActiveDocument.Range.XML,  _
"c:/Transforms/toc.xsl"
End If
End Sub

验证文档

使用 XML 架构的其中一个优点在于根据架构定义用于文档中的标记来验证任意特定文档的能力。使用架构时,如果用户插入新标记,Word 2003 就会在以下两个位置标记冲突:XML 任务窗格和文档本身中。

生成的消息是常规 XML 错误消息(首次插入某个元素时的典型消息是“Some required content is missing”)。这些消息不会为用户提供实际的指导,即不能提供消除验证错误确切应该执行什么操作。

Word 2003 使您可以自定义在文档中为任意节点生成的消息。对于任意节点,您可以调用节点的 SetValidationError 方法,传递 ValidationStatus 常量、要显示在验证错误上的消息以及指示消息是否自动清除的标记。

在此例中,当验证错误出现在 TOC 元素上时,该代码会添加一则新消息。该消息会提供有关带有目录的 Docbook 中所要求的详细信息:

Private Sub wrd_XMLValidationError(ByVal XMLNode As XMLNode)
If XMLNode.BaseName = "toc" Then
XMLNode.SetValidationError wdXMLValidationStatusCustom, _
"You must insert a title or tocentry element", True
End If
End Sub

您可以控制何时发生验证。Word 2003 的默认值是根据当前使用的架构验证更改文档文本的每个用户操作。因此,管理验证的第一步是关闭 Word 的自动验证:

ActiveDocument.XMLSchemaReferences.AutomaticValidation = False

还可以通过调用 XMLSchemaReferencesValidate 方法来验证整个文档,或者通过调用它的 Validate 方法只验证单个节点。以下代码只验证第二个节点及其子节点:

ActiveDocument.XMLNodes(2).Validate

为了使 Validate 方法运行,您必须将 XMLSchemaReferencesAutomaticValidation 属性再次设置为 True

在调用 Validate 方法后,您可以检查任意节点的 ValidateStatus 方法以确定是否发现了错误。还可以处理文档的 XMLSchemaViolations 集合中的节点以发现错误中的所有节点。以下代码会显示与具有验证错误的每个节点相关联的错误消息:

Dim nd As XMLNode
For Each nd In ActiveDocument.XMLSchemaViolations
   Msgbox nd.ValidationErrorText
Next

保存文档

当完成文档后,您希望保存它。如果尚未完成文档就可保存文档,则您可能希望设置文档所用架构的 AllowSaveAsXMLWithoutValidation 属性。这样可以防止只由于文档的所有必需部分尚未填写完毕而收到错误消息。

Document 对象的 Save 方法仍然会保存完整的 Word 2003 文档。将 Document 对象的 XMLSaveDataOnly 属性设置为 True 会导致 Word 2003 仅将与架构相关联的标记保存到文档的文件中。将 Document 对象的 XMLUseXSLTWhenSaving 设置为 True 会导致 XSLT 转换应用到文档并保存转换的输出。如果将 XMLUseXSLTWhenSaving 设置为 True,也必须将 XMLSaveThroughXSLT 属性设置为包含 XSLT 代码的文件的路径名。最后,您必须将文档的格式设置为 XML。

例如,以下代码使用 ConvertToFOMM.XSL 样式表仅保存文档中添加的、与架构相关的标记:

ActiveDocument.XMLSaveDataOnly = True
ActiveDocument.XMLSaveThroughXSLT = _
"c:\Transforms\ConvertToHTML.XSL"
ActiveDocument.XMLUseXSLTWhenSaving = True
ActiveDocument.SaveAs MyDocument.HTM, wdFormatXML

应该在使用 XSLT 转换保存该文档之前,根据其架构对该文档进行验证。尽管可以将 SchemaReferences 集合的 AllowSaveAsXMLWithoutValidation 属性设置为 True,但是根据无效文档处理 XSLT 样式表的结果将无法预计。

利用该代码创建的只有 XML 数据的文档并不包括原始 Word 2003 文档包括的所有信息。所有 WordML 标记都会丢失,而且通常情况下,新文档中的数据是原始 Word 2003 文档中的数据的子集。因此,您还希望保存原始的 Word 2003 文档以保留其中的所有信息。实现上述想法的最简单的方法就是将 XSMLSaveDataOnlyUseXSLTWhenSaving 属性设置为 False,并且执行另一个保存:

ActiveDocument.XMLSaveDataOnly = False
ActiveDocument.XMLUseXSLTWhenSaving = False
ActiveDocument.Save

小结

Word 2003 通过将 XML 集成到其对象模型中,获得了很多功能。这种集成提供了创建应用程序所需要的工具,这些应用程序利用 XML 来支持文档创建。通过利用自定义代码扩展 Word 2003 的基本功能,您可以为用户提供新级别的支持。

作者简介

Peter Vogel 一位 Office 和 .NET 开发方面的顾问。他著有 Visual Basic Object and Component Handbook(Prentice Hall PTR,2000, ISBN:0-13023-0731),并担任 Smart Access 时事通讯的编辑。

 
2008-01-19 14:35
楼主flyboy81(【欧尼油】一切都要靠自己*韬光养晦*)2006-11-05 02:52:00 在 VC/MFC / HTML/XML 提问

在微软的网站上看到关于这个Script Error的处理方法。
http://support.microsoft.com/default.aspx?scid=kb;en-us;261003

没看明白,有几个问题。
=============
当之一脚本引擎遇到处理错误, 转发错误到 WebBrowser 控件, 它然后查询其容器以查看如果容器有实现 IOleCommandTarget 。
-----------------------
问题:这个要实现的IOleCommandTarget,是作为类WebBrowser2的成员实现?还是作为我的WebBrowser控件所在的对话框类CMYDlg的成员实现?
==================================

=====================
这个接口IOleCommandTarget的实现在网上也没找到个MFC下的例子,自己看别人的实现另外一个接口的代码,依葫芦画瓢写了一下,不知道对不对?
class WebBrowser2 : public class CWin
{
..............
..............
BEGIN_INTERFACE_PART(OleCommandTarget, IOleCommandTarget)
STDMETHOD(QueryStatus) (
/* [unique][in] */ const GUID *pguidCmdGroup,
/* [in] */ ULONG cCmds,
/* [out][in][size_is] */ OLECMD prgCmds[ ],
/* [unique][out][in] */ OLECMDTEXT *pCmdText);
STDMETHOD(Exec)(
/* [unique][in] */ const GUID *pguidCmdGroup,
/* [in] */ DWORD nCmdID,
/* [in] */ DWORD nCmdexecopt,
/* [unique][in] */ VARIANT *pvaIn,
/* [unique][out][in] */ VARIANT *pvaOut);
END_INTERFACE_PART(OleCommandTarget)
}
.cpp中的在此省略
================

=================
如果容器已实现 IOleCommandTarget , WebBrowser 控件调用 OLECMDID_SHOWSCRIPTERROR 命令 ID 和 CGID_DocHostCommandHandler (其中 Mshtmhst.h 文件中定义) 的命令组 ID IOleCommandTarget::Exec 方法。
-----------------------
问题:如果已经实现了IOleCommandTarget接口,那出现脚本错误的时候,WebBrowser怎么调用IOleCommandTarget::Exec 方法?是在WebBrowser中哪里可以判断出脚本错误了?(这个问题好像解决了第一个问题,似乎IOleCommandTarget应该实现在WebBrowser2中。不知道对不对)
这里我的理解是:当有脚本错误发生的时候,在WebBrowser2中实现的接口方法IOleCommandTarget::Exec会被自动调用,在函数参数中会指明当前发生了脚本错误OLECMDID_SHOWSCRIPTERROR 。但是难以理解的是,这样的结果,难道仅仅是因为在WebBrowser实现了IOleCommandTarget接口?好像说不通,还是我不知道?总之很乱,搞不清楚他们的关系。
===============================


我要在WebBrowser上显示一个页面,当出现脚本错误的时候,做一些额外的处理,同时不希望那个Script error对话框出现。所以找到这个因为脚本错误,而引起响应的地方是个关键。


哎,整了大半天了,还是没搞明白,希望高人指点一下,谢谢先。 问题点数:100、回复次数:21

1 楼jiangsheng(蒋晟.Net[MVP])回复于 2006-11-05 06:51:25 得分 30

blog.joycode.com/jiangsheng/archive/2005/07/09/58754.aspx

2 楼flyboy81(【欧尼油】一切都要靠自己*韬光养晦*)回复于 2006-11-05 13:00:03 得分 0

to jiangsheng
那部分的代码大体的意思明白了,但是我在实现的时候还是有些疑问:
class CDHtmlExploreControlSite: public CBrowserControlSite
这里的CBrowserControlSite是哪里来的呢?我在MSDN中没有查到。

在例子中的对话框使用的类是继承于CDHtmlDialog,而我本地建的对话框是继承于CDialog,该如何使用CDHtmlDialog呢?本地的SDK是2003的支持VC6的最新的SDK。
多谢了。

3 楼flyboy81(【欧尼油】一切都要靠自己*韬光养晦*)回复于 2006-11-05 13:03:24 得分 0

我在VCKBASE上找到如下例子:
http://www.vckbase.com/article/atl/013820610.htm
对于我处理Script Error有些帮助,但是他的实现方法好像和jiangsheng 提供的方法有区别。
在vckbase的这个例子中他并没有提到如何将这个派生出来的CMyOleControl 和CWebBrowser和CDialog联系起来。
迷惑。。。。。

4 楼jiangsheng(蒋晟.Net[MVP])回复于 2006-11-05 14:57:23 得分 10

CBrowserControlSite is an undocumented MFC class
to use it in CDialog you need to copy some code from the MFC source code of CDHtmlDialog

The difference of handling command in ActiveX and in ActiveX host is the command set being called. Script error won't be redirected to ActiveX.

5 楼flyboy81(【欧尼油】一切都要靠自己*韬光养晦*)回复于 2006-11-05 18:59:58 得分 0

VC6 下有实现的可能么?

6 楼jiangsheng(蒋晟.Net[MVP])回复于 2006-11-05 23:53:55 得分 10

Sure
http://support.microsoft.com/kb/196835/EN-US/

7 楼hasia(hasia)回复于 2006-11-06 21:17:36 得分 20

我看到msdn上说CHtmlView::ExecFormsCommand的功能是
Executes the specified command using the IOleCommandTarget::Exec method

可是当我override这个函数时,依然会弹出脚本错误对话框
我的代码如下:
HRESULT CHtmlCtrl::ExecFormsCommand(DWORD dwCommandID, VARIANT *pVarIn, VARIANT *pVarOut)
{
HRESULT hr;

switch(dwCommandID) {
case OLECMDID_SHOWSCRIPTERROR:
//Don't show the error dialog,but continue to run script
pVarOut->vt=VT_BOOL;
pVarOut->boolVal=VARIANT_TRUE;
hr=S_OK;
return hr;
default:
break;
}
return CHtmlView::ExecFormsCommand(dwCommandID,pVarIn,pVarOut);
}


请问一下,我哪个地方错了

谢谢了

8 楼hasia(hasia)回复于 2006-11-06 21:27:39 得分 1

jiangsheng(蒋晟.Net[MVP]) :

能不能给个详细点的例子?
让我们看的明白点
谢谢

9 楼jiangsheng(蒋晟.Net[MVP])回复于 2006-11-07 09:05:23 得分 0

There is a bug in Visual C 2002 and 2003 that CHtmlView::ExecFormsCommand does not pass the corrent parameter to the internal implementation. Use Visual C 2005, or use IOleCommandTarget directly.

This is an example
BEGIN_INTERFACE_PART(OleCommandTarget, IOleCommandTarget)
STDMETHOD(QueryStatus)(const GUID*, ULONG, OLECMD*, OLECMDTEXT*);
STDMETHOD(Exec)(const GUID*, DWORD, DWORD, VARIANTARG*, VARIANTARG*);
END_INTERFACE_PART(OleCommandTarget)

STDMETHODIMP CBrowserControlSiteEx::XOleCommandTarget::Exec(const GUID*
pguidCmdGroup,
DWORD nCmdID,
DWORD nCmdexecopt,
VARIANTARG* pvaIn,
VARIANTARG* pvaOut )
{
METHOD_PROLOGUE_EX_(CBrowserControlSiteEx, OleCommandTarget)

HRESULT hr = S_OK;
if (pguidCmdGroup && IsEqualGUID(*pguidCmdGroup,
CGID_DocHostCommandHandler))
{
switch (nCmdID)
{
case OLECMDID_SHOWSCRIPTERROR:
{
IHTMLDocument2* pDoc = NULL;
IHTMLWindow2* pWindow = NULL;
IHTMLEventObj* pEventObj = NULL;
BSTR rgwszNames[5] =
{
SysAllocString(L"errorLine"),
SysAllocString(L"errorCharacter"),
SysAllocString(L"errorCode"),
SysAllocString(L"errorMessage"),
SysAllocString(L"errorUrl")
};
DISPID rgDispIDs[5];
VARIANT rgvaEventInfo[5];
DISPPARAMS params;
BOOL fContinueRunningScripts = true;
int i;
params.cArgs = 0;
params.cNamedArgs = 0;

// Get the document that is currently being viewed.
hr = pvaIn->punkVal->QueryInterface(IID_IHTMLDocument2, (void **)
&pDoc);

// Get document.parentWindow.
hr = pDoc->get_parentWindow(&pWindow);
pDoc->Release();

// Get the window.event object.
hr = pWindow->get_event(&pEventObj);

// Get the error info from the window.event object.
for (i = 0; i < 5; i )
{
// Get the property's dispID.
hr = pEventObj->GetIDsOfNames(IID_NULL, &rgwszNames[i], 1,
LOCALE_SYSTEM_DEFAULT, &rgDispIDs[i]);

// Get the value of the property.
hr = pEventObj->Invoke(rgDispIDs[i], IID_NULL,LOCALE_SYSTEM_DEFAULT,
DISPATCH_PROPERTYGET, &params, &rgvaEventInfo[i],NULL, NULL);

SysFreeString(rgwszNames[i]);
}

// At this point, you would normally alert the user with
// the information about the error, which is now contained
// in rgvaEventInfo[]. Or, you could just exit silently.
(*pvaOut).vt = VT_BOOL;

//if (fContinueRunningScripts)
//{
// Continue running scripts on the page.
(*pvaOut).boolVal = VARIANT_TRUE;
//}
//else
//{
// Stop running scripts on the page.
// (*pvaOut).boolVal = VARIANT_FALSE;
//}
break;
}
case OLECMDID_SHOWMESSAGE:
//(*pvaOut).boolVal = VARIANT_TRUE;
break;

default:
hr = OLECMDERR_E_NOTSUPPORTED;
break;
}
}
else
{
hr = OLECMDERR_E_UNKNOWNGROUP;
}
return (hr);

}

10 楼guti_milan()回复于 2006-11-07 09:32:35 得分 0

之前也遇到了类似情况
不过还好看了微软知识库一切都明白了
不过里面还是有些需要注意的就是
CControlSite和COccManager类的用法!
可以借鉴一下
http://www.webasp.net/article/4/3177_print.htm

11 楼hasia(hasia)回复于 2006-11-07 10:42:53 得分 0

to jiangsheng(蒋晟.Net[MVP]) :
谢谢你的回答,不过还是有点问题

我用的VisualC++2005 professional版,还是会弹出脚本错误?
我在pVarOut->vt=VT_BOOL;这里设置了断点,
一直没有调用

用IOleCommandTarget方法,弹出了很多错误
难道还需要什么头文件或者库文件吗?msdn上好像没有说啊

warning C4002: too many actual parameters for macro 'DECLARE_INTERFACE_MAP'

error LNK2001: unresolved external symbol "protected: virtual struct AFX_INTERFACEMAP const * __thiscall CHtmlCtrl::GetInterfaceMap(void)const " (?GetInterfaceMap@CHtmlCtrl@@MBEPBUAFX_INTERFACEMAP@@XZ)

error LNK2001: unresolved external symbol "public: virtual long __stdcall CHtmlCtrl::XOleCommandTarget::QueryInterface(struct _GUID const &,void * *)" (?QueryInterface@XOleCommandTarget@CHtmlCtrl@@UAGJABU_GUID@@PAPAX@Z)

error LNK2001: unresolved external symbol "public: virtual unsigned long __stdcall IUnknown::AddRef(void)" (?AddRef@IUnknown@@UAGKXZ)

error LNK2001: unresolved external symbol "public: virtual unsigned long __stdcall IUnknown::Release(void)" (?Release@IUnknown@@UAGKXZ)

error LNK2001: unresolved external symbol "public: virtual long __stdcall IOleCommandTarget::QueryStatus(struct _GUID const *,unsigned long,struct _tagOLECMD * const,struct _tagOLECMDTEXT *)" (?QueryStatus@IOleCommandTarget@@UAGJPBU_G
UID@@KQAU_tagOLECMD@@PAU_tagOLECMDTEXT@@@Z)

error LNK2001: unresolved external symbol "public: virtual long __stdcall IOleCommandTarget::Exec(struct _GUID const *,unsigned long,unsigned long,struct tagVARIANT *,struct tagVARIANT *)" (?Exec@IOleCommandTarget@@UAGJPBU_GUID@@KKPAU
tagVARIANT@@1@Z)



另外,我是在.cpp中手动添加的这些函数实现的
CHtmlCtrl继承自CHtmlView

ULONG CHtmlCtrl::XOleCommandTarget::AddRef()
{
METHOD_PROLOGUE_EX_(CHtmlCtrl, OleCommandTarget) //这一句去掉也一样
return IOleCommandTarget::AddRef();
}

ULONG CHtmlCtrl::XOleCommandTarget::Release()
{
METHOD_PROLOGUE_EX_(CHtmlCtrl, OleCommandTarget) //这一句去掉也一样

return IOleCommandTarget::Release();
}

12 楼hasia(hasia)回复于 2006-11-07 10:44:32 得分 0

我这个程序的目的是在对话框中显示网页
所以用CHtmlCtrl继承CHtmlView

13 楼jiangsheng(蒋晟.Net[MVP])回复于 2006-11-07 10:52:22 得分 0

You need to implement the interfaces in your browser site, not your browser.
For more information, see
http://msdn.microsoft.com/workshop/browser/hosting/wbcustomization.asp
and look into MFC source code.

14 楼hasia(hasia)回复于 2006-11-07 15:22:14 得分 0

to jiangsheng(蒋晟.Net[MVP])
如果我用的是CHtmlView,让CHtmlView和CStatic关联,进行显示的
没有用WebBrowser

有什么好的办法吗?
谢谢了

15 楼hasia(hasia)回复于 2006-11-07 17:43:11 得分 0

我重新写了一个web browse site类
但是还是会像上面说的一样,有很多unresolved external symbol 出现,
难道真的需要什么库吗?
没看到msdn上说啊


在vc6和vc2005上都这样,郁闷


class CCustomWebBrowserSite : public COleControlSite
{
public:
CCustomWebBrowserSite(COleControlContainer *pContainer);
virtual ~CCustomWebBrowserSite();
protected:
DECLARE_INTERFACE_MAP()

BEGIN_INTERFACE_PART(OleCommandTarget,IOleCommandTarget)
STDMETHOD(QueryStatus)(const GUID *pguidCommandGroup, ULONG cCmds,OLECMD prgCmds[],OLECMDTEXT *pCmdText);
STDMETHOD(Exec)(const GUID *pguidCmdGroup,DWORD nCmdID,DWORD nCmdexecopt,VARIANT *pvaIn,VARIANT *pvaOut);
END_INTERFACE_PART(OleCommandTarget)

};


不知道谁能说一下,谢谢了

16 楼superarhow(苏泊尔耗)回复于 2006-11-08 13:43:18 得分 12

建议做一个本线程的CALLWNDPROC的hook。因为ScripError接口函数在用户将浏览器选项设置为“允许脚本调试”时,就不会被触发了。而MSDN上提供的另一种方法,向网页中强制添加onerror的处理函数,这只能在网页加载完成后做,网页加载过程中的脚本错误也无法捕捉。

17 楼hasia(hasia)回复于 2006-11-08 15:19:55 得分 0

因为ScripError接口函数在用户将浏览器选项设置为“允许脚本调试”时,就不会被触发了。

____________________________________________________________________
____________________________________________________________________


我试过了,不行的,我去掉了浏览器中的“禁用脚本调试(Internet Explorer)”和“禁用脚本调试(其他)”这两个前面的勾,还是有脚本错误弹出来。

18 楼jiangsheng(蒋晟.Net[MVP])回复于 2006-11-09 06:42:36 得分 0

unresolved external symbol? what is your error message?

19 楼Jarod_He()回复于 2006-11-13 16:18:15 得分 0

我也遇到同样的问题 不知谁有解决办法?

20 楼superarhow(苏泊尔耗)回复于 2006-11-15 10:31:15 得分 7

我试过了,不行的,我去掉了浏览器中的“禁用脚本调试(Internet Explorer)”和“禁用脚本调试(其他)”这两个前面的勾,还是有脚本错误弹出来。
======================================
就是说去掉这个勾后,你即使实现了IOleCommandTarget这个接口,也不会被调用,仍然会转缺省的调出对话框过程处理,就是那个“是否要调试”。所以实现这个接口是解决不了这个问题的。
偶也在项目中遇到过这个问题,是通过hook本线程的CALLWNDPROC来做的。那个对话框的类名是“Internet Explorer_TridentDlgFrame”,是一个IE对话框。

21 楼Jarod_He()回复于 2006-11-15 14:08:04 得分 10

m_pWebBrowser->put_Silent( VARIANT_TRUE ); 解决问题.
现在还有一个问题,如果页面有脚本错误就无法正确的得到页面完成的消息.

 
2008-01-12 9:28

Lightweight XML Editing in Word 2003 by Evan Lenz -- Strictly speaking, you can edit custom XML in Word, but there are limitations that make the process needlessly complex. This article presents a lightweight approach to XML editing in Word that works in all editions of Word 2003. All you need besides Word is an XSLT processor. Evan Lenz, coauthor of Office 2003 XML, shows you how.

Did you know that Word documents can be saved in XML format? As of Microsoft Office 2003, the second option in Word's Save As dialog--right under "Word Document (*.doc)"--is "XML Document (*.xml)". This format is Microsoft's own XML vocabulary for Word documents, called WordprocessingML (or sometimes just WordML).

Figure 1

The ability to save Word documents as XML is arguably the most important XML-related feature introduced in Word 2003. But you wouldn't know it from all the hype surrounding Word's new support for customer schemas. When Microsoft announced that Word would let you edit XML documents that conform to your own schema (not just the WordprocessingML one), we were rightly intrigued and even excited. The promise of using the world's most popular word processor to edit, say, Docbook documents was nothing less than astounding, and it caused quite a stir in the XML community.

Hope Deferred

Now that the dust has settled and Office 2003 has been available for almost a year, we've got a clearer picture of reality. While the XML features in Word, Excel, Access, and the new InfoPath application are truly impressive and useful, it's clear that Word 2003 doesn't support arbitrary XML editing. At least it doesn't line up with the picture Microsoft painted originally. For one, the custom schema functionality is available only with Office Professional or the stand-alone Word 2003. More importantly, the features don't live up to the hype. While, strictly speaking, you can edit custom XML in Word, you're limited to using schemas that have a very static, fill-in-the-blanks structure. That means no optional or repeating elements and certainly no mixed content--that is, if you want a minimally user-friendly experience.

Or you could force your users to apply XML elements to portions of their document manually, using the new XML Structure task pane with Show XML Tags turned on. In that case, yes, they could edit arbitrary XML documents, even those with mixed content. And yes, Word will let them know if they've done something invalid (though it won't stop them from doing it). But since the user has to do all the work, and since XML elements cannot be associated with style information, the experience is not close to being user friendly (let alone WYSIWYG).

Or you could try to script in all the user friendliness by hand through the new Document Actions task pane. Of course, you should plan on joining a monastery to learn Smart Document programming and the attendant asceticism you'll need in order to appreciate the usability (or lack thereof) of your efforts' final results. (Tell me again, why are we using Word?)

Or (finally) you could come to terms with the fact that the most important (and robust) XML feature that was introduced in Word 2003 is its capability to save documents in a lossless, well-formed, open XML format called WordprocessingML. Ways to use it for generating, transforming, converting, querying, and otherwise processing Word documents are only starting to be realized. Editing custom XML may not be WordprocessingML's killer app, but it does raise some interesting possibilities that we'll explore here.

A Lightweight XSLT-Based Approach

This article presents a lightweight approach to XML editing in Word. It's "lightweight" in that it ignores all of Word's built-in custom schema functionality. A nice side effect of this approach is that it works in all editions of Word 2003. All you need outside of Word is an XSLT processor. (If you do happen to have the advanced XML functionality, you can make use of Word's bundled XSLT processor, but that's not required.)

This approach to editing will work only when your XML format is isomorphic to the structure and styles of your Word documents. The document's markup will only be as rich as the styles that are applied to it, so this rules out full-on Docbook editing. Word doesn't work well for editing recursive markup structures in general, because it doesn't support recursive styles. Each paragraph has exactly one paragraph style, and each character is associated with exactly one character style. (Word does, however, provide a convenient representation of heading levels as hierarchical subsections, using the <wx:sub-section> element, which we'll see referenced in our example below.)

You can make a complete XML editing solution for Word by writing two XSLT style sheets:

  1. A style sheet to transform from your custom XML to WordprocessingML, and
  2. A style sheet to transform from WordprocessingML back to your custom XML.

The basic scenario goes like this: to edit a custom XML document, it must get transformed by XSLT (No. 1) into WordprocessingML so that a user can edit it in Word. After the user is finished editing the document, the resulting WordprocessingML must be transformed again (No. 2), back to the custom XML format.

Note: This article does not introduce WordprocessingML except by example. For more thorough coverage, refer to the Office 2003 XML sample chapter available online, called "The WordprocessingML Vocabulary" (PDF).

An Example

Before we look at the XSLT, here's a document that conforms to a dead-simple, Docbook-esque format that we'll be editing:

<?xml version="1.0"?>
<?mso-application progid="Word.Document"?>
<?xml-stylesheet type="text/xsl" href="article2wordml.xsl"?>
<article>
  <title>This is the article title</title>
  <section>
    <title>First section</title>
    <para>This is the <emphasis>first</emphasis> paragraph.</para>
    <para>This is the <strong>second</strong> paragraph.</para>
  </section>
  <section>
    <title>Second section</title>
    <para>This section will have some sub-sections.</para>
    <section>
      <title>First sub-section</title>
      <para>This is the paragraph text of the first sub-section.</para>
    </section>
    <section>
      <title>Second sub-section</title>
      <para>This is the paragraph text of the second sub-section.</para>
      <para>And here is another paragraph, just for the fun of it--with a
<a href="http://www.xmlportfolio.com/">hyperlink</a> to boot!</para>
    </section>
  </section>
</article>

Here is what we want this document to look like while it's being edited in Word:

Figure 2

As you can see, the XML has a few examples of mixed content, which are rendered in Word using character styles (italic, bold, and blue/underlined). The hierarchical sections of the XML document are rendered using a heading for each title (Heading 1 for the article title, and Heading 2, Heading 3, and so on for successively deep section titles).

The Code

Assuming we have this XML document lying around already and we want to let people edit it, we'll need an XSLT style sheet to transform it to WordprocessingML (style sheet No. 1 in the list above). This file is called article2wordml.xsl. It contains various template rules that map elements from the custom XML to elements and styles defined in WordprocessingML. For example, to turn <emphasis> elements into character runs with the Emphasis character style, we use the following template rule:

<!-- For text in <emphasis>, apply the "Emphasis" character style -->
  <xsl:template match="emphasis/text()">
    <w:r>
      <w:rPr>
        <w:rStyle w:val="Emphasis"/>
      </w:rPr>
      <w:t>
        <xsl:value-of select="."/>
      </w:t>
    </w:r>
  </xsl:template>

To turn section titles into hierarchical headings, we use this template rule:

<!-- Convert section titles to "Heading X" paragraphs -->
  <xsl:template match="section/title">
    <w:p>
      <w:pPr>
        <w:pStyle w:val="Heading{count(ancestor::section)+1}"/>
      </w:pPr>
      <xsl:apply-templates/>
    </w:p>
  </xsl:template>

Once a user has made changes to the document from within Word, a new WordprocessingML document is saved and must be translated back to the custom XML format using style sheet No. 2 mentioned above. This style sheet, called wordml2article.xsl, has similar rules, except that they reflect the reverse mapping--from WordprocessingML to our custom XML format. For example, here's the rule that turns text in the Emphasis style into an <emphasis> element:

<!-- turn a run with the "Emphasis" character style into <emphasis> -->
  <xsl:template match="w:r[w:rPr/w:rStyle/@w:val='Emphasis']"
                mode="para-content">
    <emphasis>
      <xsl:copy-of select="w:t/text()"/>
    </emphasis>
  </xsl:template>

Here are the rules that convert the Heading paragraphs back to sections with titles:

<!-- Convert <wx:sub-section> elements to <section> elements -->
  <xsl:template match="wx:sub-section">
    <section>
      <xsl:apply-templates/>
    </section>
  </xsl:template>

<!-- Convert <w:p> paragraphs to <para> paragraphs -->
  <xsl:template match="w:p">
    <para>
      <xsl:apply-templates mode="para-content"/>
    </para>
  </xsl:template>

<!-- ...except for the first paragraph in a sub-section (Heading 1,2,3,...);
       the heading will be the <title> of the section -->
  <xsl:template match="wx:sub-section/w:p[1]">
    <title>
      <xsl:apply-templates mode="para-content"/>
    </title>
  </xsl:template>

For a complete investigation of the style sheets (including descriptive comments), see the full text of these files:

 
2007-12-28 11:16
Designing Smart Documents in Office 2003
Today, most organizations have a wealth of Office documents that contain critical information, but finding, extracting, and reusing that information programmatically remains a largely unrealized goal. Fortunately, that's changing as XML processing in Microsoft Office 2003 grows up.

uplication of effort in gathering information is an increasingly familiar scenario in many companies today. For example, an employee complains, "I've already submitted my expense report to finance, and now you want me to re-enter it in this intranet portal app?" In this scenario the employee must enter expense information for approval from his/her manager and also file another separate expense report for settlement via finance because many finance departments use financial software packages that aren't integrated with the company's intranet portal. Such isolated duplicative systems give rise to the concept of "scattered data islands," many of which are never repurposed.


You may dismiss this case as a simple integration problem, but consider how many times you've come across similar situations. For example, you may have submitted a well-documented list of components created in your previous projects to the company's intranet knowledge base portal. Your current project could reuse one of those components, but querying the document management system/portal may not find your previous documentation. Even if it does, you may need to perform a manual search to find the required information within the document. These conditions arise because the products used for development lack an integrated solution framework. Microsoft SharePoint portals addressed some of these issues, but the biggest issue is that companies have lacked a means to create intelligent repurposable documents.

Office 2003 can help solve such problems. Office 2003 supports an XML representation of content, so you can treat an entire Word document as a well-formed XML document. XML alleviates the problem of dealing with proprietary formats by letting you author templates based on XML schema (XSD). The XML content can then be filled in through automation, from databases, or Web services, or through data entry directly by users. In either case, the goal is that you can subsequently use the predefined schema to access the content of those documents, searching, altering, or retrieving any defined content within them using standard XML processing techniques.

Microsoft's "Smart Document" concept provides considerable flexibility to achieve this goal. It makes documents context-sensitive based on the schema definitions, letting you create rich, client interactive applications, and produces output in a standard XML form that you can repurpose as needed.

The idea of context-sensitive documents isn't new, but until now, it's been common only in well-defined narrow applications. Office extends the potential for context sensitivity to any document based on a schema.

Here's an example. Imagine that you've created an element in the document. When editing, a user points to that node and immediately the Office API identifies your tag definition and responds to it appropriately, perhaps providing a pick list or checking to make sure the entered information is valid. The process of defining the element, hooking it up to the Office API and providing a custom response when a user selects the tag is all programmable. This programmability leads to highly interactive and "intelligent" documents. For example, you can easily restrict which parts of a document a given user can change. Creating smart documents based on schema opens up a completely new arena of programming.

You can build and deploy such solutions in two ways, via the classic COM route or by using managed .NET code. If you choose the managed code option you can use the Visual Studio.NET Tools for Office 2003, which provides core template-based project solutions. Alternatively, you can build managed DLLs that use COM Interop to communicate with the Office applications. Either way, the bad news is that Office 2003 doesn't support any managed SDK. That's a big disadvantage; however, in most cases the advantages of using managed code outweighs the disadvantages of having to distribute the .NET framework and the performance penalties of COM Interop.
Page 1 of 11

 
2007-12-25 17:27

Microsoft Office 2003 SP3 正式版补丁
Microsoft Office 2003 SP3今日发布,大家可以从Office更新或微软更新页面,或者从这个地址直接下载到。SP3包英文版是120MB,其他语言版不超过140MB,使用自动更新功能可以在几周后更新。

  主要更新:

  如果Office 2003用户打包由Office 2007创建的文件,该文件重新使用Office 2007打开时原来Office 2007特有的数据仍然还在。

  如果有Excel文件损坏,SP3后提供尝试修复选项。

  在使用IE7将Web邮件内容复制到Word中导致Word 2003崩溃的问题得到修复。

  可以在Vista中给Access安装插件,可以打开有不同版本Access创建的数据库项目,然后在无错情况下立即创建Access数据库扩展。

 
2007-12-24 10:12
    前面用VC编译的OCX可以在网页中很好的显示Word文档和进行编辑保存了,下面需要在ASP.NET下对给定的Web服务器上的文档进行处理,需要用C#进行开发。
    我的计算机上是Windows XP,Office 2003,安装时候选择的是一路回车,在网上搜搜后,和VB下没什么大的区别,在Visual Studio 2003中生成一个ASP.NET应用,引用MicroSoft Office 11.0 Type Library,可搞来搞去就是没有Word相关的类,也没有网上说的Word.ApplicationClass等,后来在MS网上了解到需要Interop程序集,从网上下载这个东西安装,还是没有,后又在MS中Office开发中看到Office2003在NET环境下开发需要安装NET编程库,找到以前的Office安装包从新安装,在安装选项上看到确实是需要选择才能安装的,如下图。
    重新安装后,在VS2003里重新添加引用,发现有MicroSoft Word 11.0 Object Library,添加引用后,工程引用项里多了三项,分别是MicroSoft Office Core、VBIDE和Word,using Microsoft.Office.Interop.Word,可以用Word.ApplicationClass等相关类。
    然后开始进行启动Word,添加文档等相关操做,运行出错,异常好像是没有权限,我把路径设置为Web服务器的路径,http://10.210.9.74/AAAA/test.doc,运行还是出错,通过Google进行搜索,在Web.Config中添加节:<identity impersonate="true"/>,再运行,不出错了,但是保存文件没有保存,再ApplicationClass退出时直接弹出Word的保存对话框了,这个肯定是不行了,直接找原因!
    在网上找了半天,还是MS说的清楚,C#开发和VB.NET用时是不一样的,对于变量C#中不能使用可选项,每个参数都不能少,好多变量不能随便用System.Reflection.Missing.Value,都要用引用变量(ref标志),从新在Word中录制操做的宏,打开VBA编辑器,对照C#代码和宏代码,一个一个的赋值,OK,搞定。
    总结,进行Office在NET环境的开发,首先安装Office2003的NET可编程性组件以支持NET环境,再安装Office2003的Interop程序集;Web.config中添加权限节以支持ASP.NET对文件的权限;C#开发的话,不能随便设置参数变量为默认的Missing.Value;如果要操做Web服务器上的文档,还要打开服务器上WinDAV服务;
    下面是部分代码,起始很简单,只要不走弯路,还是没什么东西的:
using System;
using System.Collections;
using Microsoft.Office.Interop.Word;
namespace SNEPC.OfficeApp
{
/// <summary>
///   A class include old word and new word to replace in word document.
/// </summary>
public class WordField
{
   #region Fields
   private string _fieldName;
   private string _fieldValue;
   #endregion
   #region Properties
   /// <summary>
   ///   Old word to replace.
   /// </summary>
   public string FieldName
   {
    get
    {
     return _fieldName;
    }
    set
    {
     _fieldName = value;
    }
   }
   
   /// <summary>
   ///   New word for replace.
   /// </summary>
   public string FieldValue
   {
    get
    {
     return _fieldValue;
    }
    set
    {
     _fieldValue = value;
    }
   }
   #endregion
   #region Constructor
   public WordField(){}
   public WordField(string fieldName,string fieldValue)
   {
    _fieldName = fieldName;
    _fieldValue = fieldValue;
   }
   #endregion
}
/// <summary>
/// WordApp 的摘要说明。
/// </summary>
public class WordApp
{
   #region Fields
   private static ApplicationClass app;
   private Document doc;
   #endregion
   #region Constructor
   public WordApp()
   {
   
   }
   #endregion
   #region Methods
   /// <summary>
   ///   This method will create a new word document with a special templete file, and replace some word with param replaceValues.
   /// </summary>
   /// <param name="templeteName">
   ///   Word templete file, dot file or doc file, new file will include this file contents.
   /// </param>
   /// <param name="replaceValues">
   ///   A Array of replace values, object of array is class WordField.
   /// </param>
   /// <param name="fileName">
   ///   New file name to save.
   /// </param>
   /// <returns>
   ///   True is success, otherwise false.
   /// </returns>
   public bool CreateNewDocumentWithTemplete(string templeteName,ArrayList replaceValues,string fileName)
   {
    try
    {
     object missing = System.Reflection.Missing.Value;
     object objFalse = false;
     object objTrue = true;
     object objString = templeteName;
     app = new ApplicationClass();
     app.Visible = false;
     doc = app.Documents.Add(ref objString,ref objFalse,ref missing,ref objFalse);
     doc.Activate();
     int i;
     WordField wf;
     object wdRp = WdReplace.wdReplaceAll;
     object wdSF = WdSaveFormat.wdFormatDocument;
     object wdSO = WdSaveOptions.wdSaveChanges;
     object wdOF = WdOriginalFormat.wdWordDocument;
     object wdLE = WdLineEndingType.wdCRLF;
     object wdEc = Microsoft.Office.Core.MsoEncoding.msoEncodingHZGBSimplifiedChinese;
     for(i=0;i<replaceValues.Count;i++)
     {
      wf = (WordField)replaceValues[i];
      app.Selection.Find.ClearFormatting();
      app.Selection.Find.Text=wf.FieldName;
      app.Selection.Find.Replacement.Text = wf.FieldValue;
      app.Selection.Find.Forward = true;
      app.Selection.Find.Format=false;
      app.Selection.Find.MatchCase = false;
      app.Selection.Find.MatchWholeWord = false;
      app.Selection.Find.MatchByte = true;
      app.Selection.Find.MatchWildcards = false;
      app.Selection.Find.MatchSoundsLike = false;
      app.Selection.Find.MatchAllWordForms = false;
      app.Selection.Find.Wrap = WdFindWrap.wdFindContinue;
      app.Selection.Find.Execute(ref missing,ref missing,ref missing,ref missing,ref missing,ref missing,ref missing,ref missing,ref missing,ref missing,ref wdRp,ref missing,ref missing,ref missing,ref missing);
     }
     objString = fileName;
     object objNullString = "";
     doc.SaveAs(ref objString,ref wdSF,ref objFalse,ref objNullString,ref objTrue,ref objNullString,ref objFalse,ref objFalse,ref objFalse,ref objFalse,ref objFalse,ref wdEc,ref objFalse,ref objFalse,ref wdLE,ref objFalse);
     app.Application.Quit(ref missing,ref missing,ref missing);
    }
    catch(Exception e)
    {
     throw e;
    }
    return true;
   }
   #endregion
}
}
 
2007-11-28 14:27
文章编号 : 822510
最后修改 : 2006年3月30日
修订 : 2.1

概要

如果您将 Word 2003 邮件合并主文档另存为 XML、HTML 或 MHTML,并且邮件合并文档被连接到邮件合并数据源,则在记事本等文本编辑器中打开邮件合并主文档的保存副本时,主键列的数据将可见。

更多信息

当 Word 2003 打开 XML、HTML 或 MHTML 文档时将出现此行为,邮件合并中每个记录的可见性将被保存,并且您无须在“邮件合并收件人”对话框中重新选择要使用的记录。

下列选项可帮助您确保您的邮件合并数据源和记录不会被无意访问:
请不要将标识信息用作邮件合并数据源中的主键。

- 或者 -
不要以 XML、HTML 或 MHTM 格式保存您的邮件合并主文档。
有关其他信息,请单击下面的文章编号,以查看 Microsoft 知识库中相应的文章:
825576 (http://support.microsoft.com/kb/825576/) HOW TO:Minimize Metadata in Microsoft Word 2003

这篇文章中的信息适用于:
Microsoft Office Word 2003

回到顶端

关键字:
kbinfo KB822510
Microsoft和/或其各供应商对于为任何目的而在本服务器上发布的文件及有关图形所含信息的适用性,不作任何声明。 所有该等文件及有关图形均"依样"提供,而不带任何性质的保证。Microsoft和/或其各供应商特此声明,对所有与该等信息有关的保证和条件不负任何责任,该等保证和条件包括关于适销性、符合特定用途、所有权和非侵权的所有默示保证和条件。在任何情况下,在由于使用或运行本服务器上的信息所引起的或与该等使用或运行有关的诉讼中,Microsoft和/或其各供应商就因丧失使用、数据或利润所导致的任何特别的、间接的、衍生性的损害或任何因使用而丧失所导致的之损害、数据或利润不负任何责任。

 
2007-11-16 13:57

1.把段落末的向下的“箭头”(Htm中的软回车符)改成word中的段落标记符(Htm中的硬回车符)
       编辑---替换----点高级,点特殊符号那项,“替换”里选那个手工换行符(从下数第五个吧),“替换为”里选第一个,段落标记,然后全部替换!!搞定~也可以直接填^l和^p,分别对应软回车和硬回车~

       2.网上下的文一般中间都空一行或几行,也可以用替换,不过要在第一栏里输(选)两次^l^l,第二栏选^p,或第一栏两次^p^p,第二栏一次^p,这是去一行空格的做法

 
   
 
 
文章存档
 
     
 
最新文章评论
  

楼主在吗,有以下几个问题需要咨询以下您老人家 1、你那个破解文件还有吗?可能的话
 

点我看片
 

回复A:sdfww
 

求更新 ,,QQ用不了,密码错误
 

qq:2352176151密码:rationalrose 密码错误,麻烦更新一下可以吗?
   
帮助中心 | 空间客服 | 投诉中心 | 空间协议
©2012 Baidu