For God so loved the world, that He gave His only begotten Son, that all who believe in Him should not perish but have everlasting life
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.

448 lines
17 KiB

  1. <?php
  2. /**
  3. * PHPExcel_Writer_Excel2007_Workbook
  4. *
  5. * Copyright (c) 2006 - 2015 PHPExcel
  6. *
  7. * This library is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU Lesser General Public
  9. * License as published by the Free Software Foundation; either
  10. * version 2.1 of the License, or (at your option) any later version.
  11. *
  12. * This library is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * Lesser General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Lesser General Public
  18. * License along with this library; if not, write to the Free Software
  19. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  20. *
  21. * @category PHPExcel
  22. * @package PHPExcel_Writer_Excel2007
  23. * @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
  24. * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
  25. * @version ##VERSION##, ##DATE##
  26. */
  27. class PHPExcel_Writer_Excel2007_Workbook extends PHPExcel_Writer_Excel2007_WriterPart
  28. {
  29. /**
  30. * Write workbook to XML format
  31. *
  32. * @param PHPExcel $pPHPExcel
  33. * @param boolean $recalcRequired Indicate whether formulas should be recalculated before writing
  34. * @return string XML Output
  35. * @throws PHPExcel_Writer_Exception
  36. */
  37. public function writeWorkbook(PHPExcel $pPHPExcel = null, $recalcRequired = false)
  38. {
  39. // Create XML writer
  40. $objWriter = null;
  41. if ($this->getParentWriter()->getUseDiskCaching()) {
  42. $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory());
  43. } else {
  44. $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_MEMORY);
  45. }
  46. // XML header
  47. $objWriter->startDocument('1.0', 'UTF-8', 'yes');
  48. // workbook
  49. $objWriter->startElement('workbook');
  50. $objWriter->writeAttribute('xml:space', 'preserve');
  51. $objWriter->writeAttribute('xmlns', 'http://schemas.openxmlformats.org/spreadsheetml/2006/main');
  52. $objWriter->writeAttribute('xmlns:r', 'http://schemas.openxmlformats.org/officeDocument/2006/relationships');
  53. // fileVersion
  54. $this->writeFileVersion($objWriter);
  55. // workbookPr
  56. $this->writeWorkbookPr($objWriter);
  57. // workbookProtection
  58. $this->writeWorkbookProtection($objWriter, $pPHPExcel);
  59. // bookViews
  60. if ($this->getParentWriter()->getOffice2003Compatibility() === false) {
  61. $this->writeBookViews($objWriter, $pPHPExcel);
  62. }
  63. // sheets
  64. $this->writeSheets($objWriter, $pPHPExcel);
  65. // definedNames
  66. $this->writeDefinedNames($objWriter, $pPHPExcel);
  67. // calcPr
  68. $this->writeCalcPr($objWriter, $recalcRequired);
  69. $objWriter->endElement();
  70. // Return
  71. return $objWriter->getData();
  72. }
  73. /**
  74. * Write file version
  75. *
  76. * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer
  77. * @throws PHPExcel_Writer_Exception
  78. */
  79. private function writeFileVersion(PHPExcel_Shared_XMLWriter $objWriter = null)
  80. {
  81. $objWriter->startElement('fileVersion');
  82. $objWriter->writeAttribute('appName', 'xl');
  83. $objWriter->writeAttribute('lastEdited', '4');
  84. $objWriter->writeAttribute('lowestEdited', '4');
  85. $objWriter->writeAttribute('rupBuild', '4505');
  86. $objWriter->endElement();
  87. }
  88. /**
  89. * Write WorkbookPr
  90. *
  91. * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer
  92. * @throws PHPExcel_Writer_Exception
  93. */
  94. private function writeWorkbookPr(PHPExcel_Shared_XMLWriter $objWriter = null)
  95. {
  96. $objWriter->startElement('workbookPr');
  97. if (PHPExcel_Shared_Date::getExcelCalendar() == PHPExcel_Shared_Date::CALENDAR_MAC_1904) {
  98. $objWriter->writeAttribute('date1904', '1');
  99. }
  100. $objWriter->writeAttribute('codeName', 'ThisWorkbook');
  101. $objWriter->endElement();
  102. }
  103. /**
  104. * Write BookViews
  105. *
  106. * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer
  107. * @param PHPExcel $pPHPExcel
  108. * @throws PHPExcel_Writer_Exception
  109. */
  110. private function writeBookViews(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel $pPHPExcel = null)
  111. {
  112. // bookViews
  113. $objWriter->startElement('bookViews');
  114. // workbookView
  115. $objWriter->startElement('workbookView');
  116. $objWriter->writeAttribute('activeTab', $pPHPExcel->getActiveSheetIndex());
  117. $objWriter->writeAttribute('autoFilterDateGrouping', '1');
  118. $objWriter->writeAttribute('firstSheet', '0');
  119. $objWriter->writeAttribute('minimized', '0');
  120. $objWriter->writeAttribute('showHorizontalScroll', '1');
  121. $objWriter->writeAttribute('showSheetTabs', '1');
  122. $objWriter->writeAttribute('showVerticalScroll', '1');
  123. $objWriter->writeAttribute('tabRatio', '600');
  124. $objWriter->writeAttribute('visibility', 'visible');
  125. $objWriter->endElement();
  126. $objWriter->endElement();
  127. }
  128. /**
  129. * Write WorkbookProtection
  130. *
  131. * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer
  132. * @param PHPExcel $pPHPExcel
  133. * @throws PHPExcel_Writer_Exception
  134. */
  135. private function writeWorkbookProtection(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel $pPHPExcel = null)
  136. {
  137. if ($pPHPExcel->getSecurity()->isSecurityEnabled()) {
  138. $objWriter->startElement('workbookProtection');
  139. $objWriter->writeAttribute('lockRevision', ($pPHPExcel->getSecurity()->getLockRevision() ? 'true' : 'false'));
  140. $objWriter->writeAttribute('lockStructure', ($pPHPExcel->getSecurity()->getLockStructure() ? 'true' : 'false'));
  141. $objWriter->writeAttribute('lockWindows', ($pPHPExcel->getSecurity()->getLockWindows() ? 'true' : 'false'));
  142. if ($pPHPExcel->getSecurity()->getRevisionsPassword() != '') {
  143. $objWriter->writeAttribute('revisionsPassword', $pPHPExcel->getSecurity()->getRevisionsPassword());
  144. }
  145. if ($pPHPExcel->getSecurity()->getWorkbookPassword() != '') {
  146. $objWriter->writeAttribute('workbookPassword', $pPHPExcel->getSecurity()->getWorkbookPassword());
  147. }
  148. $objWriter->endElement();
  149. }
  150. }
  151. /**
  152. * Write calcPr
  153. *
  154. * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer
  155. * @param boolean $recalcRequired Indicate whether formulas should be recalculated before writing
  156. * @throws PHPExcel_Writer_Exception
  157. */
  158. private function writeCalcPr(PHPExcel_Shared_XMLWriter $objWriter = null, $recalcRequired = true)
  159. {
  160. $objWriter->startElement('calcPr');
  161. // Set the calcid to a higher value than Excel itself will use, otherwise Excel will always recalc
  162. // If MS Excel does do a recalc, then users opening a file in MS Excel will be prompted to save on exit
  163. // because the file has changed
  164. $objWriter->writeAttribute('calcId', '999999');
  165. $objWriter->writeAttribute('calcMode', 'auto');
  166. // fullCalcOnLoad isn't needed if we've recalculating for the save
  167. $objWriter->writeAttribute('calcCompleted', ($recalcRequired) ? 1 : 0);
  168. $objWriter->writeAttribute('fullCalcOnLoad', ($recalcRequired) ? 0 : 1);
  169. $objWriter->endElement();
  170. }
  171. /**
  172. * Write sheets
  173. *
  174. * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer
  175. * @param PHPExcel $pPHPExcel
  176. * @throws PHPExcel_Writer_Exception
  177. */
  178. private function writeSheets(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel $pPHPExcel = null)
  179. {
  180. // Write sheets
  181. $objWriter->startElement('sheets');
  182. $sheetCount = $pPHPExcel->getSheetCount();
  183. for ($i = 0; $i < $sheetCount; ++$i) {
  184. // sheet
  185. $this->writeSheet(
  186. $objWriter,
  187. $pPHPExcel->getSheet($i)->getTitle(),
  188. ($i + 1),
  189. ($i + 1 + 3),
  190. $pPHPExcel->getSheet($i)->getSheetState()
  191. );
  192. }
  193. $objWriter->endElement();
  194. }
  195. /**
  196. * Write sheet
  197. *
  198. * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer
  199. * @param string $pSheetname Sheet name
  200. * @param int $pSheetId Sheet id
  201. * @param int $pRelId Relationship ID
  202. * @param string $sheetState Sheet state (visible, hidden, veryHidden)
  203. * @throws PHPExcel_Writer_Exception
  204. */
  205. private function writeSheet(PHPExcel_Shared_XMLWriter $objWriter = null, $pSheetname = '', $pSheetId = 1, $pRelId = 1, $sheetState = 'visible')
  206. {
  207. if ($pSheetname != '') {
  208. // Write sheet
  209. $objWriter->startElement('sheet');
  210. $objWriter->writeAttribute('name', $pSheetname);
  211. $objWriter->writeAttribute('sheetId', $pSheetId);
  212. if ($sheetState != 'visible' && $sheetState != '') {
  213. $objWriter->writeAttribute('state', $sheetState);
  214. }
  215. $objWriter->writeAttribute('r:id', 'rId' . $pRelId);
  216. $objWriter->endElement();
  217. } else {
  218. throw new PHPExcel_Writer_Exception("Invalid parameters passed.");
  219. }
  220. }
  221. /**
  222. * Write Defined Names
  223. *
  224. * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer
  225. * @param PHPExcel $pPHPExcel
  226. * @throws PHPExcel_Writer_Exception
  227. */
  228. private function writeDefinedNames(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel $pPHPExcel = null)
  229. {
  230. // Write defined names
  231. $objWriter->startElement('definedNames');
  232. // Named ranges
  233. if (count($pPHPExcel->getNamedRanges()) > 0) {
  234. // Named ranges
  235. $this->writeNamedRanges($objWriter, $pPHPExcel);
  236. }
  237. // Other defined names
  238. $sheetCount = $pPHPExcel->getSheetCount();
  239. for ($i = 0; $i < $sheetCount; ++$i) {
  240. // definedName for autoFilter
  241. $this->writeDefinedNameForAutofilter($objWriter, $pPHPExcel->getSheet($i), $i);
  242. // definedName for Print_Titles
  243. $this->writeDefinedNameForPrintTitles($objWriter, $pPHPExcel->getSheet($i), $i);
  244. // definedName for Print_Area
  245. $this->writeDefinedNameForPrintArea($objWriter, $pPHPExcel->getSheet($i), $i);
  246. }
  247. $objWriter->endElement();
  248. }
  249. /**
  250. * Write named ranges
  251. *
  252. * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer
  253. * @param PHPExcel $pPHPExcel
  254. * @throws PHPExcel_Writer_Exception
  255. */
  256. private function writeNamedRanges(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel $pPHPExcel)
  257. {
  258. // Loop named ranges
  259. $namedRanges = $pPHPExcel->getNamedRanges();
  260. foreach ($namedRanges as $namedRange) {
  261. $this->writeDefinedNameForNamedRange($objWriter, $namedRange);
  262. }
  263. }
  264. /**
  265. * Write Defined Name for named range
  266. *
  267. * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer
  268. * @param PHPExcel_NamedRange $pNamedRange
  269. * @throws PHPExcel_Writer_Exception
  270. */
  271. private function writeDefinedNameForNamedRange(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_NamedRange $pNamedRange)
  272. {
  273. // definedName for named range
  274. $objWriter->startElement('definedName');
  275. $objWriter->writeAttribute('name', $pNamedRange->getName());
  276. if ($pNamedRange->getLocalOnly()) {
  277. $objWriter->writeAttribute('localSheetId', $pNamedRange->getScope()->getParent()->getIndex($pNamedRange->getScope()));
  278. }
  279. // Create absolute coordinate and write as raw text
  280. $range = PHPExcel_Cell::splitRange($pNamedRange->getRange());
  281. for ($i = 0; $i < count($range); $i++) {
  282. $range[$i][0] = '\'' . str_replace("'", "''", $pNamedRange->getWorksheet()->getTitle()) . '\'!' . PHPExcel_Cell::absoluteReference($range[$i][0]);
  283. if (isset($range[$i][1])) {
  284. $range[$i][1] = PHPExcel_Cell::absoluteReference($range[$i][1]);
  285. }
  286. }
  287. $range = PHPExcel_Cell::buildRange($range);
  288. $objWriter->writeRawData($range);
  289. $objWriter->endElement();
  290. }
  291. /**
  292. * Write Defined Name for autoFilter
  293. *
  294. * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer
  295. * @param PHPExcel_Worksheet $pSheet
  296. * @param int $pSheetId
  297. * @throws PHPExcel_Writer_Exception
  298. */
  299. private function writeDefinedNameForAutofilter(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null, $pSheetId = 0)
  300. {
  301. // definedName for autoFilter
  302. $autoFilterRange = $pSheet->getAutoFilter()->getRange();
  303. if (!empty($autoFilterRange)) {
  304. $objWriter->startElement('definedName');
  305. $objWriter->writeAttribute('name', '_xlnm._FilterDatabase');
  306. $objWriter->writeAttribute('localSheetId', $pSheetId);
  307. $objWriter->writeAttribute('hidden', '1');
  308. // Create absolute coordinate and write as raw text
  309. $range = PHPExcel_Cell::splitRange($autoFilterRange);
  310. $range = $range[0];
  311. // Strip any worksheet ref so we can make the cell ref absolute
  312. if (strpos($range[0], '!') !== false) {
  313. list($ws, $range[0]) = explode('!', $range[0]);
  314. }
  315. $range[0] = PHPExcel_Cell::absoluteCoordinate($range[0]);
  316. $range[1] = PHPExcel_Cell::absoluteCoordinate($range[1]);
  317. $range = implode(':', $range);
  318. $objWriter->writeRawData('\'' . str_replace("'", "''", $pSheet->getTitle()) . '\'!' . $range);
  319. $objWriter->endElement();
  320. }
  321. }
  322. /**
  323. * Write Defined Name for PrintTitles
  324. *
  325. * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer
  326. * @param PHPExcel_Worksheet $pSheet
  327. * @param int $pSheetId
  328. * @throws PHPExcel_Writer_Exception
  329. */
  330. private function writeDefinedNameForPrintTitles(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null, $pSheetId = 0)
  331. {
  332. // definedName for PrintTitles
  333. if ($pSheet->getPageSetup()->isColumnsToRepeatAtLeftSet() || $pSheet->getPageSetup()->isRowsToRepeatAtTopSet()) {
  334. $objWriter->startElement('definedName');
  335. $objWriter->writeAttribute('name', '_xlnm.Print_Titles');
  336. $objWriter->writeAttribute('localSheetId', $pSheetId);
  337. // Setting string
  338. $settingString = '';
  339. // Columns to repeat
  340. if ($pSheet->getPageSetup()->isColumnsToRepeatAtLeftSet()) {
  341. $repeat = $pSheet->getPageSetup()->getColumnsToRepeatAtLeft();
  342. $settingString .= '\'' . str_replace("'", "''", $pSheet->getTitle()) . '\'!$' . $repeat[0] . ':$' . $repeat[1];
  343. }
  344. // Rows to repeat
  345. if ($pSheet->getPageSetup()->isRowsToRepeatAtTopSet()) {
  346. if ($pSheet->getPageSetup()->isColumnsToRepeatAtLeftSet()) {
  347. $settingString .= ',';
  348. }
  349. $repeat = $pSheet->getPageSetup()->getRowsToRepeatAtTop();
  350. $settingString .= '\'' . str_replace("'", "''", $pSheet->getTitle()) . '\'!$' . $repeat[0] . ':$' . $repeat[1];
  351. }
  352. $objWriter->writeRawData($settingString);
  353. $objWriter->endElement();
  354. }
  355. }
  356. /**
  357. * Write Defined Name for PrintTitles
  358. *
  359. * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer
  360. * @param PHPExcel_Worksheet $pSheet
  361. * @param int $pSheetId
  362. * @throws PHPExcel_Writer_Exception
  363. */
  364. private function writeDefinedNameForPrintArea(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null, $pSheetId = 0)
  365. {
  366. // definedName for PrintArea
  367. if ($pSheet->getPageSetup()->isPrintAreaSet()) {
  368. $objWriter->startElement('definedName');
  369. $objWriter->writeAttribute('name', '_xlnm.Print_Area');
  370. $objWriter->writeAttribute('localSheetId', $pSheetId);
  371. // Setting string
  372. $settingString = '';
  373. // Print area
  374. $printArea = PHPExcel_Cell::splitRange($pSheet->getPageSetup()->getPrintArea());
  375. $chunks = array();
  376. foreach ($printArea as $printAreaRect) {
  377. $printAreaRect[0] = PHPExcel_Cell::absoluteReference($printAreaRect[0]);
  378. $printAreaRect[1] = PHPExcel_Cell::absoluteReference($printAreaRect[1]);
  379. $chunks[] = '\'' . str_replace("'", "''", $pSheet->getTitle()) . '\'!' . implode(':', $printAreaRect);
  380. }
  381. $objWriter->writeRawData(implode(',', $chunks));
  382. $objWriter->endElement();
  383. }
  384. }
  385. }