You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

excelant.xml 15KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!--
  3. ====================================================================
  4. Licensed to the Apache Software Foundation (ASF) under one or more
  5. contributor license agreements. See the NOTICE file distributed with
  6. this work for additional information regarding copyright ownership.
  7. The ASF licenses this file to You under the Apache License, Version 2.0
  8. (the "License"); you may not use this file except in compliance with
  9. the License. You may obtain a copy of the License at
  10. http://www.apache.org/licenses/LICENSE-2.0
  11. Unless required by applicable law or agreed to in writing, software
  12. distributed under the License is distributed on an "AS IS" BASIS,
  13. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. See the License for the specific language governing permissions and
  15. limitations under the License.
  16. ====================================================================
  17. -->
  18. <!DOCTYPE document PUBLIC "-//APACHE//DTD Documentation V1.1//EN" "../dtd/document-v11.dtd">
  19. <document>
  20. <header>
  21. <title>ExcelAnt - Ant Tasks for Validating Excel Spreadsheets</title>
  22. <authors>
  23. <person email="jon@loquatic.com" name="Jon Svede" id="JDS"/>
  24. <person email="brian.bush@nrel.gov" name="Brian Bush" id="BWB"/>
  25. </authors>
  26. </header>
  27. <body>
  28. <section><title>ExcelAnt - Ant Tasks for Validating Excel Spreadsheets</title>
  29. <section><title>Introduction</title>
  30. <p>ExcelAnt is a set of Ant tasks that make it possible to verify or test
  31. a workbook without having to write Java code. Of course, the tasks themselves
  32. are written in Java, but to use this frame work you only need to know a little
  33. bit about Ant.</p>
  34. <p>This document covers the basic usage and set up of ExcelAnt.</p>
  35. <p>This document will assume basic familiarity with Ant and Ant build files.</p>
  36. </section>
  37. <section><title>Setup</title>
  38. <p>To start with, you'll need to have the POI 3.8 or higher jar files. If you test only .xls
  39. workbooks then you need to have the following jars in your path:</p>
  40. <ul>
  41. <li>poi-excelant-$version-YYYYDDMM.jar</li>
  42. <li>poi-$version-YYYYDDMM.jar</li>
  43. <li>poi-ooxml-$version-YYYYDDMM.jar</li>
  44. </ul>
  45. <p> If you evaluate .xlsx workbooks then you need to add these: </p>
  46. <ul>
  47. <li>poi-ooxml-schemas-$version-YYYYDDMM.jar</li>
  48. <li>xmlbeans.jar</li>
  49. <li>dom4j.jar</li>
  50. </ul>
  51. <p>For example, if you have these jars in a lib/ dir in your project, your build.xml
  52. might look like this:</p>
  53. <source><![CDATA[
  54. <property name="lib.dir" value="lib" />
  55. <path id="excelant.path">
  56. <pathelement location="${lib.dir}/poi-excelant-3.8-beta1-20101230.jar" />
  57. <pathelement location="${lib.dir}/poi-3.8-beta1-20101230.jar" />
  58. <pathelement location="${lib.dir}/poi-ooxml-3.8-beta1-20101230.jar" />
  59. </path>
  60. ]]></source>
  61. <p>Next, you'll need to define the Ant tasks. There are several ways to use ExcelAnt:</p>
  62. <ul><li>The traditional way:</li></ul>
  63. <source><![CDATA[
  64. <typedef resource="org/apache/poi/ss/excelant/antlib.xml" classpathref="excelant.path" />
  65. ]]></source>
  66. <p>
  67. Where excelant.path referes to the classpath with POI jars.
  68. Using this approach the provided extensions will live in the default namespace. Note that the default task/typenames (evaluate, test) may be too generic and should either be explicitly overridden or used with a namespace.
  69. </p>
  70. <ul><li>Similar, but assigning a namespace URI:</li></ul>
  71. <source><![CDATA[
  72. <project name="excelant-demo" xmlns:poi="antlib:org.apache.poi.ss.excelant">
  73. <typedef resource="org/apache/poi/ss/excelant/antlib.xml"
  74. classpathref="excelant.classpath"
  75. uri="antlib:org.apache.poi.ss.excelant"/>
  76. <target name="test-nofile">
  77. <poi:excelant>
  78. </poi:excelant>
  79. </target>
  80. </project>
  81. ]]></source>
  82. </section>
  83. <section><title>A Simple Example</title>
  84. <p>The simplest example of using Excel is the ability to validate that POI is giving you back
  85. the value you expect it to. Does this mean that POI is inaccurate? Hardly. There are cases
  86. where POI is unable to evaluate cells for a variety of reasons. If you need to write code
  87. to integrate a worksheet into an app, you may want to know that it's going to work before
  88. you actually try to write that code. ExcelAnt helps with that.</p>
  89. <p>Consider the mortgage-calculation.xls file found in the Examples
  90. (/examples/src/org/apache/poi/ss/examples/excelant/simple-mortgage-calculation.xls). This sheet
  91. is shown below:</p>
  92. <!--img src="../resources/images/simple-xls-with-function.jpg" alt="mortgage calculation spreadsheet"/-->
  93. <p>This sheet calculates the principal and interest payment for a mortgage based
  94. on the amount of the loan, term and rate. To write a simple ExcelAnt test you
  95. need to tell ExcelAnt about the file like this:</p>
  96. <source><![CDATA[
  97. <property name="xls.file" value="" />
  98. <target name="simpleTest">
  99. <excelant fileName="${xls.file}">
  100. <test name="checkValue" showFailureDetail="true">
  101. <evaluate showDelta="true" cell="'MortgageCalculator'!$B$4" expectedValue="790.7936" precision="1.0e-4" />
  102. </test>
  103. </excelant>
  104. </target>
  105. ]]></source>
  106. <p>This code sets up ExcelAnt to access the file defined in the ant property
  107. xls.file. Then it creates a 'test' named 'checkValue'. Finally it tries
  108. to evaluate the B4 on the sheet named 'MortgageCalculator'. There are some assumptions
  109. here that are worth explaining. For starters, ExcelAnt is focused on the testing
  110. numerically oriented sheets. The &lt;evaluate&gt; task is actually evaluating the
  111. cell as a formula using a FormulaEvaluator instance from POI. Therefore it will fail
  112. if you point it to a cell that doesn't contain a formula or a test a plain old number.</p>
  113. <p>Having said all that, here is what the output looks like:</p>
  114. <source><![CDATA[
  115. simpleTest:
  116. [excelant] ExcelAnt version 0.4.0 Copyright 2011
  117. [excelant] Using input file: resources/excelant.xls
  118. [excelant] 1/1 tests passed.
  119. BUILD SUCCESSFUL
  120. Total time: 391 milliseconds
  121. ]]></source>
  122. </section>
  123. <section><title>Setting Values into a Cell</title>
  124. <p>So now we know that at a minimum POI can use our sheet to calculate the existing value.
  125. This is an important point: in many cases sheets have dependencies, i.e., cells they reference.
  126. As is often the case, these cells may have dependencies, which may have dependencies, etc.
  127. The point is that sometimes a dependent cell may get adjusted by a macro or a function
  128. and it may be that POI doesn't have the capabilities to do the same thing. This test
  129. verifies that we can rely on POI to retrieve the default value, based on the stored values
  130. of the sheet. Now we want to know if we can manipulate those dependencies and verify
  131. the output.</p>
  132. <p>To verify that we can manipulate cell values, we need a way in ExcelAnt to set a value.
  133. This is provided by the following task types:</p>
  134. <ul>
  135. <li>setDouble() - sets the specified cell as a double.</li>
  136. <li>setFormula() - sets the specified cell as a formula.</li>
  137. <li>setString() = sets the specified cell as a String.</li>
  138. </ul>
  139. <p>For the purposes of this example we'll use the &lt;setDouble&gt; task. Let's
  140. start with a $240,000, 30 year loan at 11% (let's pretend it's like 1984). Here
  141. is how we will set that up:</p>
  142. <source><![CDATA[
  143. <setDouble cell="'MortgageCalculator'!$B$1" value="240000"/>
  144. <setDouble cell="'MortgageCalculator'!$B$2" value ="0.11"/>
  145. <setDouble cell="'MortgageCalculator'!$B$3" value ="30"/>
  146. <evaluate showDelta="true" cell="'MortgageCalculator'!$B$4" expectedValue="2285.576149" precision="1.0e-4" />
  147. ]]></source>
  148. <p>Don't forget that we're verifying the behavior so you need to put all this
  149. into the sheet. That is how I got the result of $2,285 and change. So save your
  150. changes and run it; you should get the following: </p>
  151. <source><![CDATA[
  152. Buildfile: C:\opt\eclipse\workspaces\excelant\excelant.examples\build.xml
  153. simpleTest:
  154. [excelant] ExcelAnt version 0.4.0 Copyright 2011
  155. [excelant] Using input file: resources/excelant.xls
  156. [excelant] 1/1 tests passed.
  157. BUILD SUCCESSFUL
  158. Total time: 406 milliseconds
  159. ]]></source>
  160. </section>
  161. <section><title>Getting More Details</title>
  162. <p>This is great, it's working! However, suppose you want to see a little more detail. The
  163. ExcelAnt tasks leverage the Ant logging so you can add the -verbose and -debug flags to
  164. the Ant command line to get more detail. Try adding -verbose. Here is what
  165. you should see:</p>
  166. <source><![CDATA[
  167. simpleTest:
  168. [excelant] ExcelAnt version 0.4.0 Copyright 2011
  169. [excelant] Using input file: resources/excelant.xls
  170. [evaluate] test precision = 1.0E-4 global precision = 0.0
  171. [evaluate] Using evaluate precision of 1.0E-4
  172. [excelant] 1/1 tests passed.
  173. BUILD SUCCESSFUL
  174. Total time: 406 milliseconds
  175. ]]></source>
  176. <p>We see a little more detail. Notice that we see that there is a setting for global precision.
  177. Up until now we've been setting the precision on each evaluate that we call. This
  178. is obviously useful but it gets cumbersome. It would be better if there were a way
  179. that we could specify a global precision - and there is. There is a &lt;precision&gt;
  180. tag that you can specify as a child of the &lt;excelant&gt; tag. Let's go back to
  181. our original task we set up earlier and modify it:</p>
  182. <source><![CDATA[
  183. <property name="xls.file" value="" />
  184. <target name="simpleTest">
  185. <excelant fileName="${xls.file}">
  186. <precision value="1.0e-3"/>
  187. <test name="checkValue" showFailureDetail="true">
  188. <evaluate showDelta="true" cell="'MortgageCalculator'!$B$4" expectedValue="790.7936" />
  189. </test>
  190. </excelant>
  191. </target>
  192. ]]></source>
  193. <p>In this example we have set the global precision to 1.0e-3. This means that
  194. in the absence of something more stringent, all tests in the task will use
  195. the global precision. We can still override this by specifying the
  196. precision attribute of all of our &lt;evaluate&gt; task. Let's first run
  197. this task with the global precision and the -verbose flag:</p>
  198. <source><![CDATA[
  199. simpleTest:
  200. [excelant] ExcelAnt version 0.4.0 Copyright 2011
  201. [excelant] Using input file: resources/excelant.xls
  202. [excelant] setting precision for the test checkValue
  203. [test] setting globalPrecision to 0.0010 in the evaluator
  204. [evaluate] test precision = 0.0 global precision = 0.0010
  205. [evaluate] Using global precision of 0.0010
  206. [excelant] 1/1 tests passed.
  207. ]]></source>
  208. <p>As the output clearly shows, the test itself has no precision but there is
  209. the global precision. Additionally, it tells us we're going to use that
  210. more stringent global value. Now suppose that for this test we want
  211. to use a more stringent precision, say 1.0e-4. We can do that by adding
  212. the precision attribute back to the &lt;evaluate&gt; task:</p>
  213. <source><![CDATA[
  214. <excelant fileName="${xls.file}">
  215. <precision value="1.0e-3"/>
  216. <test name="checkValue" showFailureDetail="true">
  217. <setDouble cell="'MortgageCalculator'!$B$1" value="240000"/>
  218. <setDouble cell="'MortgageCalculator'!$B$2" value ="0.11"/>
  219. <setDouble cell="'MortgageCalculator'!$B$3" value ="30"/>
  220. <evaluate showDelta="true" cell="'MortgageCalculator'!$B$4" expectedValue="2285.576149" precision="1.0e-4" />
  221. </test>
  222. </excelant>
  223. ]]></source>
  224. <p>Now when you re-run this test with the verbose flag you will see that
  225. your test ran and passed with the higher precision:</p>
  226. <source><![CDATA[
  227. simpleTest:
  228. [excelant] ExcelAnt version 0.4.0 Copyright 2011
  229. [excelant] Using input file: resources/excelant.xls
  230. [excelant] setting precision for the test checkValue
  231. [test] setting globalPrecision to 0.0010 in the evaluator
  232. [evaluate] test precision = 1.0E-4 global precision = 0.0010
  233. [evaluate] Using evaluate precision of 1.0E-4 over the global precision of 0.0010
  234. [excelant] 1/1 tests passed.
  235. BUILD SUCCESSFUL
  236. Total time: 390 milliseconds
  237. ]]></source>
  238. </section>
  239. <section><title>Leveraging User Defined Functions</title>
  240. <p>POI has an excellent feature (besides ExcelAnt) called <link href="user-defined-functions.html">User Defined Functions</link>,
  241. that allows you to write Java code that will be used in place of custom VB
  242. code or macros is a spreadsheet. If you have read the documentation and written
  243. your own FreeRefFunction implmentations, ExcelAnt can make use of this code.
  244. For each &lt;excelant&gt; task you define you can nest a &lt;udf&gt; tag
  245. which allows you to specify the function alias and the class name.</p>
  246. <p>Consider the previous example of the mortgage calculator. What if, instead
  247. of being a formula in a cell, it was a function defined in a VB macro? As luck
  248. would have it, we already have an example of this in the examples from the
  249. User Defined Functions example, so let's use that. In the example spreadsheet
  250. there is a tab for MortgageCalculatorFunction, which will use. If you look in
  251. cell B4, you see that rather than a messy cell based formula, there is only the function
  252. call. Let's not get bogged down in the function/Java implementation, as these
  253. are covered in the User Defined Function documentation. Let's just add
  254. a new target and test to our existing build file:</p>
  255. <source><![CDATA[
  256. <target name="functionTest">
  257. <excelant fileName="${xls.file}">
  258. <udf functionAlias="calculatePayment" class="org.apache.poi.ss.examples.formula.CalculateMortgage"/>
  259. <precision value="1.0e-3"/>
  260. <test name="checkValue" showFailureDetail="true">
  261. <setDouble cell="'MortgageCalculator'!$B$1" value="240000"/>
  262. <setDouble cell="'MortgageCalculator'!$B$2" value ="0.11"/>
  263. <setDouble cell="'MortgageCalculator'!$B$3" value ="30"/>
  264. <evaluate showDelta="true" cell="'MortgageCalculatorFunction'!$B$4" expectedValue="2285.576149" precision="1.0e-4" />
  265. </test>
  266. </excelant>
  267. </target>
  268. ]]></source>
  269. <p>So if you look at this carefully it looks the same as the previous examples. We
  270. still use the global precision, we're still setting values, and we still want
  271. to evaluate a cell. The only real differences are the sheet name and the
  272. addition of the function.</p>
  273. </section>
  274. </section>
  275. </body>
  276. </document>