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.

298 lines
13 KiB

  1. <?php
  2. /**
  3. * PHPExcel_Shared_Excel5
  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_Shared
  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_Shared_Excel5
  28. {
  29. /**
  30. * Get the width of a column in pixels. We use the relationship y = ceil(7x) where
  31. * x is the width in intrinsic Excel units (measuring width in number of normal characters)
  32. * This holds for Arial 10
  33. *
  34. * @param PHPExcel_Worksheet $sheet The sheet
  35. * @param string $col The column
  36. * @return integer The width in pixels
  37. */
  38. public static function sizeCol($sheet, $col = 'A')
  39. {
  40. // default font of the workbook
  41. $font = $sheet->getParent()->getDefaultStyle()->getFont();
  42. $columnDimensions = $sheet->getColumnDimensions();
  43. // first find the true column width in pixels (uncollapsed and unhidden)
  44. if (isset($columnDimensions[$col]) and $columnDimensions[$col]->getWidth() != -1) {
  45. // then we have column dimension with explicit width
  46. $columnDimension = $columnDimensions[$col];
  47. $width = $columnDimension->getWidth();
  48. $pixelWidth = PHPExcel_Shared_Drawing::cellDimensionToPixels($width, $font);
  49. } elseif ($sheet->getDefaultColumnDimension()->getWidth() != -1) {
  50. // then we have default column dimension with explicit width
  51. $defaultColumnDimension = $sheet->getDefaultColumnDimension();
  52. $width = $defaultColumnDimension->getWidth();
  53. $pixelWidth = PHPExcel_Shared_Drawing::cellDimensionToPixels($width, $font);
  54. } else {
  55. // we don't even have any default column dimension. Width depends on default font
  56. $pixelWidth = PHPExcel_Shared_Font::getDefaultColumnWidthByFont($font, true);
  57. }
  58. // now find the effective column width in pixels
  59. if (isset($columnDimensions[$col]) and !$columnDimensions[$col]->getVisible()) {
  60. $effectivePixelWidth = 0;
  61. } else {
  62. $effectivePixelWidth = $pixelWidth;
  63. }
  64. return $effectivePixelWidth;
  65. }
  66. /**
  67. * Convert the height of a cell from user's units to pixels. By interpolation
  68. * the relationship is: y = 4/3x. If the height hasn't been set by the user we
  69. * use the default value. If the row is hidden we use a value of zero.
  70. *
  71. * @param PHPExcel_Worksheet $sheet The sheet
  72. * @param integer $row The row index (1-based)
  73. * @return integer The width in pixels
  74. */
  75. public static function sizeRow($sheet, $row = 1)
  76. {
  77. // default font of the workbook
  78. $font = $sheet->getParent()->getDefaultStyle()->getFont();
  79. $rowDimensions = $sheet->getRowDimensions();
  80. // first find the true row height in pixels (uncollapsed and unhidden)
  81. if (isset($rowDimensions[$row]) and $rowDimensions[$row]->getRowHeight() != -1) {
  82. // then we have a row dimension
  83. $rowDimension = $rowDimensions[$row];
  84. $rowHeight = $rowDimension->getRowHeight();
  85. $pixelRowHeight = (int) ceil(4 * $rowHeight / 3); // here we assume Arial 10
  86. } elseif ($sheet->getDefaultRowDimension()->getRowHeight() != -1) {
  87. // then we have a default row dimension with explicit height
  88. $defaultRowDimension = $sheet->getDefaultRowDimension();
  89. $rowHeight = $defaultRowDimension->getRowHeight();
  90. $pixelRowHeight = PHPExcel_Shared_Drawing::pointsToPixels($rowHeight);
  91. } else {
  92. // we don't even have any default row dimension. Height depends on default font
  93. $pointRowHeight = PHPExcel_Shared_Font::getDefaultRowHeightByFont($font);
  94. $pixelRowHeight = PHPExcel_Shared_Font::fontSizeToPixels($pointRowHeight);
  95. }
  96. // now find the effective row height in pixels
  97. if (isset($rowDimensions[$row]) and !$rowDimensions[$row]->getVisible()) {
  98. $effectivePixelRowHeight = 0;
  99. } else {
  100. $effectivePixelRowHeight = $pixelRowHeight;
  101. }
  102. return $effectivePixelRowHeight;
  103. }
  104. /**
  105. * Get the horizontal distance in pixels between two anchors
  106. * The distanceX is found as sum of all the spanning columns widths minus correction for the two offsets
  107. *
  108. * @param PHPExcel_Worksheet $sheet
  109. * @param string $startColumn
  110. * @param integer $startOffsetX Offset within start cell measured in 1/1024 of the cell width
  111. * @param string $endColumn
  112. * @param integer $endOffsetX Offset within end cell measured in 1/1024 of the cell width
  113. * @return integer Horizontal measured in pixels
  114. */
  115. public static function getDistanceX(PHPExcel_Worksheet $sheet, $startColumn = 'A', $startOffsetX = 0, $endColumn = 'A', $endOffsetX = 0)
  116. {
  117. $distanceX = 0;
  118. // add the widths of the spanning columns
  119. $startColumnIndex = PHPExcel_Cell::columnIndexFromString($startColumn) - 1; // 1-based
  120. $endColumnIndex = PHPExcel_Cell::columnIndexFromString($endColumn) - 1; // 1-based
  121. for ($i = $startColumnIndex; $i <= $endColumnIndex; ++$i) {
  122. $distanceX += self::sizeCol($sheet, PHPExcel_Cell::stringFromColumnIndex($i));
  123. }
  124. // correct for offsetX in startcell
  125. $distanceX -= (int) floor(self::sizeCol($sheet, $startColumn) * $startOffsetX / 1024);
  126. // correct for offsetX in endcell
  127. $distanceX -= (int) floor(self::sizeCol($sheet, $endColumn) * (1 - $endOffsetX / 1024));
  128. return $distanceX;
  129. }
  130. /**
  131. * Get the vertical distance in pixels between two anchors
  132. * The distanceY is found as sum of all the spanning rows minus two offsets
  133. *
  134. * @param PHPExcel_Worksheet $sheet
  135. * @param integer $startRow (1-based)
  136. * @param integer $startOffsetY Offset within start cell measured in 1/256 of the cell height
  137. * @param integer $endRow (1-based)
  138. * @param integer $endOffsetY Offset within end cell measured in 1/256 of the cell height
  139. * @return integer Vertical distance measured in pixels
  140. */
  141. public static function getDistanceY(PHPExcel_Worksheet $sheet, $startRow = 1, $startOffsetY = 0, $endRow = 1, $endOffsetY = 0)
  142. {
  143. $distanceY = 0;
  144. // add the widths of the spanning rows
  145. for ($row = $startRow; $row <= $endRow; ++$row) {
  146. $distanceY += self::sizeRow($sheet, $row);
  147. }
  148. // correct for offsetX in startcell
  149. $distanceY -= (int) floor(self::sizeRow($sheet, $startRow) * $startOffsetY / 256);
  150. // correct for offsetX in endcell
  151. $distanceY -= (int) floor(self::sizeRow($sheet, $endRow) * (1 - $endOffsetY / 256));
  152. return $distanceY;
  153. }
  154. /**
  155. * Convert 1-cell anchor coordinates to 2-cell anchor coordinates
  156. * This function is ported from PEAR Spreadsheet_Writer_Excel with small modifications
  157. *
  158. * Calculate the vertices that define the position of the image as required by
  159. * the OBJ record.
  160. *
  161. * +------------+------------+
  162. * | A | B |
  163. * +-----+------------+------------+
  164. * | |(x1,y1) | |
  165. * | 1 |(A1)._______|______ |
  166. * | | | | |
  167. * | | | | |
  168. * +-----+----| BITMAP |-----+
  169. * | | | | |
  170. * | 2 | |______________. |
  171. * | | | (B2)|
  172. * | | | (x2,y2)|
  173. * +---- +------------+------------+
  174. *
  175. * Example of a bitmap that covers some of the area from cell A1 to cell B2.
  176. *
  177. * Based on the width and height of the bitmap we need to calculate 8 vars:
  178. * $col_start, $row_start, $col_end, $row_end, $x1, $y1, $x2, $y2.
  179. * The width and height of the cells are also variable and have to be taken into
  180. * account.
  181. * The values of $col_start and $row_start are passed in from the calling
  182. * function. The values of $col_end and $row_end are calculated by subtracting
  183. * the width and height of the bitmap from the width and height of the
  184. * underlying cells.
  185. * The vertices are expressed as a percentage of the underlying cell width as
  186. * follows (rhs values are in pixels):
  187. *
  188. * x1 = X / W *1024
  189. * y1 = Y / H *256
  190. * x2 = (X-1) / W *1024
  191. * y2 = (Y-1) / H *256
  192. *
  193. * Where: X is distance from the left side of the underlying cell
  194. * Y is distance from the top of the underlying cell
  195. * W is the width of the cell
  196. * H is the height of the cell
  197. *
  198. * @param PHPExcel_Worksheet $sheet
  199. * @param string $coordinates E.g. 'A1'
  200. * @param integer $offsetX Horizontal offset in pixels
  201. * @param integer $offsetY Vertical offset in pixels
  202. * @param integer $width Width in pixels
  203. * @param integer $height Height in pixels
  204. * @return array
  205. */
  206. public static function oneAnchor2twoAnchor($sheet, $coordinates, $offsetX, $offsetY, $width, $height)
  207. {
  208. list($column, $row) = PHPExcel_Cell::coordinateFromString($coordinates);
  209. $col_start = PHPExcel_Cell::columnIndexFromString($column) - 1;
  210. $row_start = $row - 1;
  211. $x1 = $offsetX;
  212. $y1 = $offsetY;
  213. // Initialise end cell to the same as the start cell
  214. $col_end = $col_start; // Col containing lower right corner of object
  215. $row_end = $row_start; // Row containing bottom right corner of object
  216. // Zero the specified offset if greater than the cell dimensions
  217. if ($x1 >= self::sizeCol($sheet, PHPExcel_Cell::stringFromColumnIndex($col_start))) {
  218. $x1 = 0;
  219. }
  220. if ($y1 >= self::sizeRow($sheet, $row_start + 1)) {
  221. $y1 = 0;
  222. }
  223. $width = $width + $x1 -1;
  224. $height = $height + $y1 -1;
  225. // Subtract the underlying cell widths to find the end cell of the image
  226. while ($width >= self::sizeCol($sheet, PHPExcel_Cell::stringFromColumnIndex($col_end))) {
  227. $width -= self::sizeCol($sheet, PHPExcel_Cell::stringFromColumnIndex($col_end));
  228. ++$col_end;
  229. }
  230. // Subtract the underlying cell heights to find the end cell of the image
  231. while ($height >= self::sizeRow($sheet, $row_end + 1)) {
  232. $height -= self::sizeRow($sheet, $row_end + 1);
  233. ++$row_end;
  234. }
  235. // Bitmap isn't allowed to start or finish in a hidden cell, i.e. a cell
  236. // with zero height or width.
  237. if (self::sizeCol($sheet, PHPExcel_Cell::stringFromColumnIndex($col_start)) == 0) {
  238. return;
  239. }
  240. if (self::sizeCol($sheet, PHPExcel_Cell::stringFromColumnIndex($col_end)) == 0) {
  241. return;
  242. }
  243. if (self::sizeRow($sheet, $row_start + 1) == 0) {
  244. return;
  245. }
  246. if (self::sizeRow($sheet, $row_end + 1) == 0) {
  247. return;
  248. }
  249. // Convert the pixel values to the percentage value expected by Excel
  250. $x1 = $x1 / self::sizeCol($sheet, PHPExcel_Cell::stringFromColumnIndex($col_start)) * 1024;
  251. $y1 = $y1 / self::sizeRow($sheet, $row_start + 1) * 256;
  252. $x2 = ($width + 1) / self::sizeCol($sheet, PHPExcel_Cell::stringFromColumnIndex($col_end)) * 1024; // Distance to right side of object
  253. $y2 = ($height + 1) / self::sizeRow($sheet, $row_end + 1) * 256; // Distance to bottom of object
  254. $startCoordinates = PHPExcel_Cell::stringFromColumnIndex($col_start) . ($row_start + 1);
  255. $endCoordinates = PHPExcel_Cell::stringFromColumnIndex($col_end) . ($row_end + 1);
  256. $twoAnchor = array(
  257. 'startCoordinates' => $startCoordinates,
  258. 'startOffsetX' => $x1,
  259. 'startOffsetY' => $y1,
  260. 'endCoordinates' => $endCoordinates,
  261. 'endOffsetX' => $x2,
  262. 'endOffsetY' => $y2,
  263. );
  264. return $twoAnchor;
  265. }
  266. }