1、功能介绍
PageOffice能实现不同用户同时编辑一个Word文档的不同区域,且保存后不会相互影响和覆盖他人编辑修改的内容。
在线对Word文档进行编辑时,可能会出现多人同时访问、编辑同一个文档中不同区域的情况,例如多个老师同时在线批改一份试卷的不同题目、多个领导审批一份文件并要在不同的地方加注不同的审批意见等等。要想实现这些功能,一般来说,在写程序时,既要给不同的用户分配不同的权限和其可编辑的区域,还要控制不同用户在编辑完自己的可编辑区域后保存文件时不能覆盖他人的编辑内容。若是只给不同用户分配不同权限是十分简单和容易实现的,在此篇文章中不再多说,但是以往的编程方法根本无法实现多个用户同时编辑Word中的不同区域,而且保存时也无法控制当前用户保存的内容不覆盖前者保存的内容。
而通过PageOffice中的数据区域(即DataRegion类)来实现不同用户同时编辑一个Word文档中不同并且保存时相互不受影响这一系列的功能就变得相当简单而容易了。
什么是数据区域?数据区域是Word文档中具有 "PO_" 前缀命名的书签所定位的文档区域。简单来说,数据区域就是一种特殊的Word书签对象,便于定位Word文档中的内容。数据区域是PageOffice开发平台中重要的技术概念。
这里举个简单的例子说明什么是数据区域:假设开发者需要在待打开的Word文档指定位置处显示产品名称,就可以先手动打开此Word文档,在指定位置处插入书签"PO_ProductName",保存文档。这样数据区域"ProductName"就定义好了。编写代码 doc.OpenDataRegion("ProductName").Value ="PageOffice"; 即可在此数据区域处生成想要的内容。
数据区域的填充及数据区域格式的控制都是通过DataRegion类实现的,很多Word操作都需要调用DataRegion类完成。DataRegion类能通过调用 OpenDataRegion(String) 方法或CreateDataRegion(String, DataRegionInsertType, String) 方法获得 DataRegion 对象。
PageOffice实现多用户同时编辑一个Word文档只需先在一个Word文档中可编辑区域的各个位置分别插入书签做成Word模版,模版中有几个可编辑区域再相应地创建几个Word文档,最后通过程序将这些Word动态填充到数据区域中就可以实现多人同时编辑一个Word文档了。
一般的开发人员使用Word比较少,可能不清楚Word书签是怎样插入的,下面简单的介绍一下插入书签的方法。
第一种方法:把光标定位到需要标记数据位置的地方,点Word菜单中的“插入”-“书签”,就会弹出一个标题为“书签”的对话框(如下图所示),输入新书签的名称,注意:书签名必须以字母、汉字、中文标点等开头,可以包含数字但中间不能有空格(用PageOffice开发的时候不推荐使用中文命名书签名)。点右侧的“添加”按钮,新的书签名将出现在下面的列表中。
第二种方法:选择几个文字、或一段文字、或者选择一段包含表格和图片的内容,为选中的内容指定书签的对象,然后执行第一种方法的同样操作,“插入”→“书签”……
注意:如果新插入位置或新对象采用的是已有的书签名,原有的书签将自动取消。
PageOffice示例代码中的模板在制作的时候,多采用第二中方法定义书签,插入书签之前会先写一个标示性的词语用中括号括起来,比如:[姓名],然后选中“[姓名]”,再插入书签。这样做的目的是便于在查看或编辑模板数据位置的时候一目了然。
在使用PageOffice开发的过程中,为了避免出现与用户自己定义的书签出现冲突,要求插入的书签名称必须以“PO_”开头。注意是字母o,不是数字0。
在PageOffice的概念里提到的数据区域,本质上就是书签,但是只有“PO_”(或者小写的“po_”)开头的书签才叫数据区域,请大家注意这点。
二、不同用户同时编辑Word文档中的不同区域的具体实现方法
PageOffice多用户同时编辑一个Word文档中的不同区域的实现过程很简单,只需要将PageOfficeCtrl控件类结合WordDocument类和DataRegion类使用即可实现,具体的实现步骤如下:
①先在一个Word文档中设置好文档的正文,再在要设置可编辑区域的各个位置分别插入书签(命名为“PO_com1”、“PO_com2”、…)做成Word模版,命名为“test.doc”。
②“test.doc”模版中设置了几个数据区域,就相应地再创建几个Word文档,分别命名为“content1.doc”、“content2.doc”等。在这些创建的Word文档中可以根据需要设置文本格式和样式。
③在程序中,通过DataRegion类将那些创建的Word文档动态填充到数据区域中。部分代码如下:
WordDocument doc = new WordDocument();
//打开数据区域
DataRegion d1 = doc.openDataRegion("PO_com1");
DataRegion d2 = doc.openDataRegion("PO_com2");
//给数据区域赋值
d1.setValue("[word]doc/content1.doc[/word]");
d2.setValue("[word]doc/content2.doc[/word]");
注意:若要多人编辑Word文件后保存时不会相互覆盖保存结果,那么,就要将各个数据区域中的内容分别保存到单独的Word文件中。因此,在动态填充数据区域时,一定要将DataRegion对象的属性“SubmitAsFile”设置为true。如下:
d1.setSubmitAsFile(true);
d2.setSubmitAsFile(true);
这样以来,在保存时PageOffice就会分别将数据区域的内容保存到单个的Word文件中。
数据区域值的类型可以是文本类型、Word文件类型、Excel文件类型、图片类型等。一般将Word、Excel、图片类型的值赋值给数据区域时,写法为:“[word]word文件路径[/word]”、“[excel]excel文件路径[/excel]”、“[image]image图片路径[/image]”。此处为了实现多人同时编辑保存一个Word文档且保存结果互不受影响的效果, 只使用Word文件类型。
PageOffice标准版只支持文本类型,专业版只支持文本、图片和Word文件类型,企业版文本、Word文件、Excel文件、Image图片类型都支持。使用时请一定要注意。
数据区域的具体使用方法和属性设置请参见相应开发语言的开发帮助和开发示例包中的示例。
④在程序中,控制不同用户对Word文档中不同数据区域的可编辑性,即设置DataRegion类对象的Editing属性,设置为true,即表示该数据区域可编辑;设置为false,则表示该数据区域不可编辑,该属性的默认值为false:
d1.Editing = true; //数据区域可编辑
d2.Editing = false; //数据区域不可编辑
⑤调用PageOfficeCtrl控件类的WebOpen(Stringfilename, OpenModeType type, String userName)方法打开Word文件(“test.doc”)。注意,为了实现提交数据区域中的数据和将其分别保存到不同的Word文件中(“content1.doc”、“content2.doc”…),WebOpen()方法中的第二个参数,即Word文档的打开模式需使用“docSubmitForm”。
⑥编辑完内容,点击保存按钮保存Word文档时,PageOffice会在保存页面中将各个数据区域内编辑的内容分别保存到各自的Word文档(“content1.doc”、“content2.doc”…)中。但是模版文档“test.doc”是不会提交和保存的,这一点请注意。还有美中不足的就是不同用户在不同数据区域内进行编辑时,页面中不能实时的显示Word中其它数据区域内的编辑内容,需保存再刷新页面后才能显示。
PageOffice不同用户同时编辑一个Word文档中不同区域并保存的部分实现代码如下:
//Java实现代码
控制不同用户同时编辑一个Word文档中不同区域的代码:
... ...
WordDocument doc = new WordDocument();
//打开数据区域
DataRegion d1 = doc.openDataRegion("PO_com1");
DataRegion d2 = doc.openDataRegion("PO_com2");
//给数据区域赋值
d1.setValue("[word]doc/content1.doc[/word]");
d2.setValue("[word]doc/content2.doc[/word]");
//若要将数据区域内容存入文件中,则必须设置属性“setSubmitAsFile”值为true
d1.setSubmitAsFile(true);
d2.setSubmitAsFile(true);
//根据登录用户名设置数据区域可编辑性
//甲客户:zhangsan登录后
if (userName.equals("zhangsan")) {
d1.setEditing(true); //设置数据区域为可编辑
d2.setEditing(false); //设置数据区域为不可编辑
}
//乙客户:lisi登录后
... ...
PageOfficeCtrl poCtrl = new PageOfficeCtrl(request);
poCtrl.setWriter(doc); //不要忘记此句
poCtrl.addCustomToolButton("保存", "Save", 1); //添加自定义保存按钮
... ...
poCtrl.setSaveDataPage("SaveData.jsp?userName=" + userName); //设置保存页
poCtrl.webOpen("doc/test.doc", OpenModeType.docSubmitForm, userName);//打开模式为:docSubmitForm
poCtrl.setTagId("PageOfficeCtrl1");//此行必须
保存页面代码:
... ...
WordDocument doc = new WordDocument(request, response);
//根据用户名判断要保存到哪个Word文件中
if (request.getParameter("userName") != null &&request.getParameter("userName").trim().equalsIgnoreCase("zhangsan")) {
bytes = doc.openDataRegion("PO_com1").getFileBytes();
filePath = "content1.doc";
}
... ...
//将文件流保存到Word文档中
FileOutputStream outputStream = new FileOutputStream(filePath);
outputStream.write(bytes);
outputStream.flush();
outputStream.close();
//C#实现代码
控制不同用户同时编辑一个Word文档中不同区域的代码:
WordDocument doc = new WordDocument();
DataRegion d1 = doc.OpenDataRegion("PO_com1");//打开数据区域
d1.Value= "[word]doc/content1.doc[/word]"; //给数据区域赋值
d1.SubmitAsFile= true; //若要将数据区域内容存入文件中,则必须设置属性“SubmitAsFile”值为true
......
//根据登录用户名设置数据区域可编辑性
//甲客户:zhangsan 登录后
if (userName.Equals("zhangsan"))
{
d1.Editing= true;
d2.Editing= false;
}
//乙客户:lisi 登录后
......
PageOfficeCtrl1.AddCustomToolButton("保存", "Save",1); //添加自定义按钮
......
PageOfficeCtrl1.SaveDataPage= "SaveData.aspx?userName=" +userName; //设置保存页
PageOfficeCtrl1.WebOpen("doc/test.doc", PageOffice.OpenModeType.docSubmitForm, userName);//打开文档
保存页面代码:
PageOffice.WordReader.WordDocument doc = newPageOffice.WordReader.WordDocument();
//判断登录的用户
if (Request.QueryString["userName"]!= null && Request.QueryString["userName"].Equals("zhangsan"))
{
saveBytesToFile(doc.OpenDataRegion("PO_com1").FileBytes, Server.MapPath("doc/content1.doc"));//保存数据区域的内容到相应的Word文档中
}
......
//保存文件流到Word文件中
private voidsaveBytesToFile(byte[] bytes, string filePath)
{
FileStream fs = new FileStream(filePath,System.IO.FileMode.OpenOrCreate);
fs.Write(bytes, 0, bytes.Length);
fs.Close();
}
上述示例的完整代码请参考相应开发语言的Samples示例包中高级功能的第19个示例:“ 控制不同用户编辑 Word 文档中不同的区域(可同时编辑) (企业版)”。