我用jacob调用word模板替换标签发挥客户端之后出现一个问题,就是如果用户在线打开word文件不关闭,那么其他用户就不能访问这个下载功能,否则会报出“word无法保存此文件,因为它已在别处打开”,说的应该是模板吧,我想这个应该是不能用同步的,请问有什么好方法解决的,或者怎么设置系统弹出来的打开保存窗口的“打开”按钮不可用或隐藏?

解决方案 »

  1.   

    你的写法有问题吧,读模板时,读进缓存,读完了就把流close了。 这样就不会有问题了。
      

  2.   

    我想过这样,不过jacob打开模板的方法封装了:this.doc = Dispatch.call(documents, "Open", template).toDispatch();  不过我去试下把close doc 的方法换个地方调用看看效果,谢了先~~
      

  3.   

    先copy一个在当前目录,然后在进行自己的操作
    操作后下载 然后删除copy的文件
      

  4.   

    我也用过jacob调用word,但没出现你说的这种情况,代码贴出来看看// 生成一个MSwordManager对象,并且设置显示Word程序
    MSWordManager ms = new MSWordManager(false);
    ms.createNewDocument();
    ms.setFont(false, false, false, "1", "15", "宋体");
    ms.title("车辆信息报告\r");
    ms.setFont(false, false, false, "1", "9", "宋体");
    ms.createTable(7, 6);
    ms.putTxtToCell(1, 1, 1, "卡口名称");
    ms.putTxtToCell(1, 1, 2, "车牌号码");
    ms.putTxtToCell(1, 1, 3, "车牌颜色");
    ms.putTxtToCell(1, 1, 4, "行驶方向");
    ms.putTxtToCell(1, 1, 5, "行驶车道");
    ms.putTxtToCell(1, 1, 6, "行驶车速");
    ms.putTxtToCell(1, 1, 7, "通过时间");
    ms.putTxtToCell(1, 2, 1, carInfoDto.getKkName());
    ms.putTxtToCell(1, 2, 2, carInfoDto.getCarNumber());
    ms.putTxtToCell(1, 2, 3, carInfoDto.getCarColor());
    ms.putTxtToCell(1, 2, 4, carInfoDto.getDirName());
    ms.putTxtToCell(1, 2, 5, carInfoDto.getWayCode() + "车道");
    ms.putTxtToCell(1, 2, 6, String.valueOf(carInfoDto.getCarSpeed())
    + "km/h");
    ms.putTxtToCell(1, 2, 7, carInfoDto.getThroughTime());
    ms.mergeCell(1, 3, 7, 3, 1);
    ms.putPicToCell(1, 3, 1, "\r近景图片", photoURL1);
    ms.mergeCell(1, 4, 7, 4, 1);
    ms.putPicToCell(1, 4, 1, "\r远景图片", photoURL2);
    ms.mergeCell(1, 5, 7, 5, 4);
    ms.putTxtToCell(1, 5, 1, "车主姓名");
    ms.putTxtToCell(1, 5, 2, "车辆类型");
    ms.putTxtToCell(1, 5, 3, "车辆品牌");
    ms.putTxtToCell(1, 5, 4, "生产厂家");
    ms.mergeCell(1, 6, 7, 6, 4);
    ms.putTxtToCell(1, 6, 1, dd.getOwnerName());
    ms.putTxtToCell(1, 6, 2, dd.getCarType());
    ms.putTxtToCell(1, 6, 3, dd.getCarBrand());
    ms.putTxtToCell(1, 6, 4, dd.getWorkShop()); Date date = new Date();
    SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    String nowTimeTemp = sd.format(date).replaceAll(":", "")
    .replaceAll("-", "");
    String[] s = nowTimeTemp.split(" ");
    String nowTime = request.getRemoteAddr().concat("@");
    for (int f = 0; f < s.length; f++) {
    nowTime += s[f].toString();
    }
    String path = "H:/doc/" + nowTime.concat(".doc");
    ms.save(path);
    ms.closeDocument();
    ms.close();
    try {
    response.setStatus(HttpServletResponse.SC_OK);
    response.setContentType("application/msword;charset=UTF-8");
    response.setHeader("Content-Disposition",
    "attachment;filename=" + nowTime + ".doc");
    File doc = new File(path);
    FileInputStream input = new FileInputStream(doc);
    BufferedInputStream buf = new BufferedInputStream(input);
    int readBytes = 0;
    response.flushBuffer();
    OutputStream stream = response.getOutputStream();
    stream.flush();
    while ((readBytes = buf.read()) != -1) {
    stream.write(readBytes);
    }
    stream.close();
    } catch (IOException e) { }
      

  5.   

    我用的模板替换书签的方法,6楼用的创建一个新word的方法。因为项目里面要导出的模板有20多个,而且好多文件中包含复杂的公式表达式用程序处理起来比较麻烦,所以我用标签替换的方法。我贴的我的代码个大家看看吧:
       
           // 在这里调用处理word的方法 
        public void savewords(String stdid,String filemodule,String tempfolder,Object object){
              DcDStdbaseinfo dcDStdbaseinfo=dcDStdbaseinfoDao.getDcDStdbaseinfo(Long.parseLong(stdid));
    Document docc =null;

    if(tempfolder.indexOf("建标申请")!=-1||tempfolder.indexOf("考核(复查)申请书")!=-1){

    String[] module = { "stdname", "stdcode", "depid" ,"stdname1"};
    String[] pulist = {dcDStdbaseinfo.getStdname(),dcDStdbaseinfo.getStdcode(),  dcDStdbaseinfo.getDep().getOrgName(),dcDStdbaseinfo.getStdname()
               };

    //  配套设备和标准器信息

            List list=getDcDevices(stdid,tempfolder);
            List bzq=null;
            List ptsb=null;
            if(list!=null&&list.size()>0){
             bzq=(List)list.get(0);
          ptsb=(List)list.get(1);
            }
     
         try {
    docc = new Document(filemodule, tempfolder);
    docc.replaceAll(module, pulist);
    if(bzq!=null&&bzq.size()>0){
      docc.replaceTable("4", 8, bzq,2);
    }
           if(ptsb!=null&&ptsb.size()>0){
      docc.replaceTable("4", 8+count, ptsb,2);
    }
    docc.save();
    } catch (Exception e)
    {
    docc.close();
    e.printStackTrace();
    }
    }
        }
        //  处理word的类
        public class Document
    { private Dispatch doc; private Dispatch documents; private ActiveXComponent word;

    private static String newFileName="";
    public Document(String template,String newFileName) 
    {
    this.newFileName=newFileName;
    this.word = new ActiveXComponent("Word.Application");
    this.documents = word.getProperty("Documents").toDispatch();
    this.doc = Dispatch.call(documents, "Open", template).toDispatch();
    }
    public void replaceAll(String [], String value[]) {
    for (int i = 0; i < .length; i++) {
    Dispatch bookMark = Dispatch.call(doc, "Books", [i]).toDispatch();
    // 其中bookMarkName是String类型,是在word模板里设置的书签名
    bookMark = Dispatch.get(bookMark, "Range").toDispatch();
    // 在全局的范围内获取
    Dispatch.put(bookMark, "Text", value[i]);
    // newText是String类型,是你想替换成的文字
    Dispatch Books = Dispatch.get(doc, "Books").toDispatch();
    Dispatch.call(Books, "Add", [i], bookMark);
    // bookMarkName是String 类型,是你想替换的书签
    } }

    public void save() {
    Dispatch.call(doc, "SaveAs", newFileName);
    // 保存word文档,其中newFile是生成文件的绝对路径
    this.close();
    }


    public void close(){
    Dispatch.call(doc, "Close", new Variant(false));
    // 关闭doc
    word.invoke("Quit", new Variant[0]);
    // 关闭word应用程序
    }

    /**
     * 替换表格
     * 
     * @param selection
     *            插入点
     * @param tableName
     *            表格名称,形如table$1@1、[email protected]$R@N,R代表从表格中的第R行开始填充,
     *            N代表word文件中的第N张表
     * @param fields
     *            表格中要替换的字段与数据的对应表
     */
    public void replaceTable( String tbIndex,int fromRow, List dataList,int movevar) {

    Dispatch selection=getSelection();

    // 所有表格
    Dispatch tables = Dispatch.get(doc, "Tables").toDispatch();
    // 要填充的表格
    Dispatch table = Dispatch.call(tables, "Item", new Variant(tbIndex))
    .toDispatch();
    // 表格的所有行
    Dispatch rows = Dispatch.get(table, "Rows").toDispatch(); // 填充表格
    for (int i = 0; i < dataList.size(); i++) {
    // 某一行数据
    String[] datas = (String[]) dataList.get(i);
    // 在表格中添加一行
    if (Dispatch.get(rows, "Count").getInt() < fromRow + i)
    Dispatch.call(rows, "Add");
    // 填充该行的相关列
    for (int j = 0; j < datas.length; j++) {
    // 得到单元格
    Dispatch cell = Dispatch.call(table, "Cell",new Variant(fromRow + i),new Variant(j+movevar)).toDispatch();
    // 选中单元格
    Dispatch.call(cell, "Select");
    // 输入数据
    Dispatch.put(selection, "Text", datas[j]!=null?datas[j].toString():"");
    }
    }
    }}
      
       
      

  6.   

    就是如果用户在线打开word文件不关闭,
    =======
    这是共享冲突问题,不可避免的。3楼、五楼使用缓冲、副本来解决都是很好的办法。另外提示一下楼主,如果碰到别人要访问正在修改的模板时该怎么办,是提示模板在修改请等待呢,还是使用旧模板,并且悄悄进村,打枪的不要呢。
    两种不同的思路,两种不同的实现,效果也不相同。
      

  7.   

    我今天已经按照5楼的思路对程序进行了修改,就是copy一个模板文件,然后对副本进行替换操作,操作结束后删掉副本,同时如果有其他用户访问就重新copy一个副本替换。理论上来说两个用户同时访问打开的并不是同一个模板文件,但是问题丝毫没有解决,连异常都没有改变,我想我还是要好好思考一下~~
      

  8.   

    1.不知道你用什么方法copy的文件
    是用File 还是jacob  要注意进程
    2.异常都一样? 你清理下工程试试 把tomcat work下的文件删除在试试
      

  9.   

    很难,看不懂,jacob是什么东西啊,一直没有听过啊,敢问大侠赐教 啊
      

  10.   

    今天把修改过的程序放在架构师的机子上运行一点问题都没有了,同时我发现报“文件已经打开不能保存”的错并不是模版已经打开的问题,而是只要我有打开word文件(与程序无关的任何word文件)就会报这个错,就是说错误与程序无关,单单是word线程共享问题,可能与我的机子环境有关,还没有想到解决办法,谢谢大家关注~~