具有自动计算功能的 pdftex 和 javascript 表格

具有自动计算功能的 pdftex 和 javascript 表格

我想用 TeX 创建带有表单的 PDF 文档。表单中的某些字段将根据其他字段的值进行计算。

以下是 MWE,感谢pdftex 邮件列表中的 Victor Ivrii2005年:

\documentclass{article}
\usepackage[pdftex]{hyperref}
\begin{document}
\begin{Form}

\TextField[maxlen=40,keystroke={AFNumber_Keystroke(2, 0, 1, 2,
true);},align=2,height=10pt,width=45pt,name=alpha]{Alpha}

\bigskip
\TextField[maxlen=40,keystroke={AFNumber_Keystroke(2, 0, 1, 2,
true);},align=2,height=10pt,width=45pt,name=beta]{Beta}


\bigskip
\TextField[maxlen=40,keystroke={AFNumber_Keystroke(2, 0, 1, 2, true);},
calculate={AFSimple_Calculate("SUM" , new Array ( "alpha" , "beta" )
;)},  align=2,height=10pt,width=45pt,name=gamma,readonly=true]{Gamma}
\end{Form}
\end{document}

生成的 PDF 有三个字段,第三个字段应该自动更新为前两个字段的总和。如果我编译文档并在 Acrobat 中打开,我可以编辑前两个字段(alphabeta),但第三个字段(gamma)不会更新。没有抛出 JavaScript 错误。

如果我在 Acrobat 中检查字段的属性gamma,我可以看到它的属性被设置为两个字段和calculate的总和。 alphabeta

Crobat 窗口和对话框

如果我选择“选择...”,系统会显示一个包含三个字段的对话框,alpha以及beta被选中。如果我取消选择并且重新选择这些字段并接受后,表单现在可按预期工作(scribd 上的 Acrobat 修改文档)。该diff命令告诉我PDF文件已经改变,但没有告诉我具体是怎么改变的。

我在 pdftex 邮件列表、上述引用的帖子中找到了有关此问题的一些讨论,并且这里。Ralf Uterman 显然发布了修补由于第二个线程,但据我所知,问题仍然存在。我尝试eformsAcroTeX 捆绑包以及,但作者写道手动的“当使用dvipsdvipsone或驱动程序时,计算可以正常工作。”(未列出)。dvipdfmpdftex

但我无法在任何驱动程序下使用它。如果我使用驱动dvips程序编译为 DVI,然后dvips转换为 PostScript,然后使用 Acrobat Distiller 转换为 PDF,我得到的表单与 一样不起作用pdftex。如果我使用dvipdf驱动程序,然后dvipdf转换为 PDF,所有表单元素都无法识别并被忽略。

此文档将在扫描的 PDF 上盖章,因此除了表格和一些基本标记外,我真的不需要其他输出。因此,我对引擎、驱动程序等很灵活,但到目前为止,如果没有通过 Acrobat 进行手动干预,我什么都做不了。我知道相关问题“hyperref:如何在表单文本字段中格式化文本“但我也无法在接受的答案中进行计算。

答案1

软件包hyperref2012/10/12 v6.83i 现在为支持 PDF 表单的三个驱动程序类(pdftex、dvipdfm/xetex、pdfmark/dvips)实现了字典中缺少的计算顺序数组/Form。如果字段元素包含计算代码,则该字段元素将自动添加到计算顺序数组中。目前仅支持文档顺序。

\documentclass{article}
\usepackage{hyperref}[2012/10/12]

\begin{document}
\begin{Form}

\TextField[maxlen=40,align=2,height=10pt,width=45pt,name=alpha]{Alpha}

\bigskip
\TextField[maxlen=40,align=2,height=10pt,width=45pt,name=beta]{Beta}

\bigskip
\TextField[
  maxlen=40,
  calculate={%
    var f_alpha = this.getField("alpha");
    var f_beta = this.getField("beta");
    event.value = f_alpha.value + f_beta.value;
  },
   align=2,height=10pt,width=45pt,name=gamma,readonly=true]{Gamma}
\end{Form}
\end{document}

更新

hyperref2012/10/13 v6.83j 起,如果使用 pdfTeX,则可以指定计算顺序README

字段选项calculatesortkey

具有计算值的字段默认按文档顺序计算。如果计算字段值依赖于文档中稍后出现的其他计算字段,则可以使用选项指定正确的计算顺序calculatesortkey。其值用作键,按字典顺序对计算字段进行排序。排序键不需要唯一。共享相同键的字段按文档顺序排序。

目前,只有pdfTeX 驱动程序calculatesortkey支持字段选项。

答案2

PDF 规范要求每个需要重新计算的表单字段都必须在计算顺序交互式形式词典的条目(参见第 416、431 页)。hyperref但不会自动执行此操作,因此查看器不会考虑您的 JavaScript。你提到的补丁应该承担这项工作,但它似乎不再起作用了,可能是因为hyperref实现方式已经发生了变化:在当前版本中,使用没有计算顺序的默认形式字典,而不是补丁创建的“正确”字典。

此解决方案将具有非空值的表单字段添加calculate到计算顺序(自动)。实现方式与创建所有表单字段的列表非常相似,如下所示hyperref

\documentclass{article}
\usepackage[pdftex]{hyperref}

\usepackage{etoolbox}
\makeatletter
\let\HyField@calcorder\ltx@empty
\Hy@AtBeginDocument{%
  \if@filesw
    \immediate\write\@mainaux{%
      \string\providecommand\string\HyField@AuxAddToCalculationOrder[1]{}%
    }%
  \fi
  \def\HyField@AuxAddToCalculationOrder#1{%
    \xdef\HyField@calcorder{%
      \ifx\HyField@calcorder\@empty
      \else
        \HyField@calcorder
        \space
      \fi
      #1 0 R%
    }%
  }%
}
\def\HyField@@AddToFields#1{%
  \HyField@AfterAuxOpen{%
    \if@filesw
      \write\@mainaux{%
        \string\HyField@AuxAddToFields{#1}%
      }%
      \ifx\Fld@calculate@code\@empty
      \else
        \write\@mainaux{%
          \string\HyField@AuxAddToCalculationOrder{#1}%
        }%
      \fi
    \fi
  }%
}%
\patchcmd{\@Form}{/Fields[\HyField@afields]}{/CO[\HyField@calcorder]/Fields[\HyField@afields]}{}{}
\makeatother

\begin{document}
\begin{Form}

\TextField[maxlen=40,keystroke={AFNumber_Keystroke(2, 0, 1, 2,
true);},align=2,height=10pt,width=45pt,name=alpha]{Alpha}

\bigskip
\TextField[maxlen=40,keystroke={AFNumber_Keystroke(2, 0, 1, 2,
true);},align=2,height=10pt,width=45pt,name=beta]{Beta}


\bigskip
\TextField[maxlen=40,keystroke={AFNumber_Keystroke(2, 0, 1, 2, true);},
calculate={AFSimple_Calculate("SUM" , new Array ( "alpha" , "beta" )
);},  align=2,height=10pt,width=45pt,name=gamma,readonly=true]{Gamma}
\end{Form}
\end{document}

具有自动计算值的表单字段

顺便说一句:在您的 MWE 中,表达式;中的calculate放错了位置,这已在上面的代码中得到纠正。


eforms包需要hyperref,但它以不同的方式实现表单字段的创建,因此上述补丁将不起作用。但是,可以通过修补 的文本字段宏来调整它,以调用生成计算顺序所需的eforms辅助命令。此代码应该适用于和hyperref创建的文本字段。hyperrefeforms

\documentclass{article}
\usepackage[pdftex]{eforms}

\usepackage{etoolbox}
\makeatletter
\let\HyField@calcorder\ltx@empty
\Hy@AtBeginDocument{
  \if@filesw
    \immediate\write\@mainaux{%
      \string\providecommand\string\HyField@AuxAddToCalculationOrder[1]{}%
    }%
  \fi
  \def\HyField@AuxAddToCalculationOrder#1{%
    \xdef\HyField@calcorder{%
      \ifx\HyField@calcorder\@empty
      \else
        \HyField@calcorder
        \space
      \fi
      #1 0 R%
    }%
  }%
}
\def\HyField@@AddToFields#1{%
  \HyField@AfterAuxOpen{%
    \if@filesw
      \write\@mainaux{%
        \string\HyField@AuxAddToFields{#1}%
      }%
      \ifx\Fld@calculate@code\@empty
        \ifisCalculate
          \write\@mainaux{%
            \string\HyField@AuxAddToCalculationOrder{#1}%
          }%
        \fi
      \else
        \write\@mainaux{%
          \string\HyField@AuxAddToCalculationOrder{#1}%
        }%
      \fi
    \fi
  }%
}%
\patchcmd{\@Form}{/Fields[\HyField@afields]}{/CO[\HyField@calcorder]/Fields[\HyField@afields]}{}{}
\patchcmd{\eq@TextField}{\hbox{\pdfstartlink user{\common@TextFieldCode}%
\lower\eqcenterWidget\ef@Bbox{\eq@rectW}{\eq@rectH}\pdfendlink}}{\hbox{\pdfstartlink user{\common@TextFieldCode}%
    \lower\eqcenterWidget\ef@Bbox{\eq@rectW}{\eq@rectH}\pdfendlink}\HyField@AddToFields}{}{}
\makeatother

\begin{document}
\begin{tabular}{@{\hspace{20pt}}rl}
Number 1: & \textField[\AA{%
    \AAKeystroke{AFNumber_Keystroke(1,1,0,0,"",true)}
    \AAFormat{AFNumber_Format(1,1,0,0,"",true)}}]{num.1}{1in}{11bp} \\[6pt]
%
Number 2: & \textField[\AA{%
    \AAKeystroke{AFNumber_Keystroke(1,1,0,0,"",true)}
    \AAFormat{AFNumber_Format(1,1,0,0,"",true)}}]{num.2}{1in}{11bp}\\[6pt]
%
Total:    & \textField[\AA{%
    \AAKeystroke{AFNumber_Keystroke(1,1,0,0,"",true)}
    \AAFormat{AFNumber_Format(1,1,0,0,"",true)}
    \AACalculate{AFSimple_Calculate("SUM", new Array("num"))}
}]{totalNum}{1in}{11bp}
\end{tabular}
\end{document}

使用电子表单自动计算表单字段

相关内容