Skip to content

Commit 3922d9a

Browse files
authored
Merge pull request #4453 from oleibman/issue56
Xls Writer Treat Hyperlink Starting with # as Internal
2 parents f9b1b76 + 8be18d1 commit 3922d9a

File tree

5 files changed

+85
-8
lines changed

5 files changed

+85
-8
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ and this project adheres to [Semantic Versioning](https://semver.org).
3131

3232
- Micro-optimization for excelToDateTimeObject. [Issue #4438](https://github.com/PHPOffice/PhpSpreadsheet/issues/4438) [PR #4442](https://github.com/PHPOffice/PhpSpreadsheet/pull/4442)
3333
- Print Area and Row Break. [Issue #1275](https://github.com/PHPOffice/PhpSpreadsheet/issues/1275) [PR #4450](https://github.com/PHPOffice/PhpSpreadsheet/pull/4450)
34+
- Xls Writer Treat Hyperlink Starting with # as Internal. [Issue #56](https://github.com/PHPOffice/PhpSpreadsheet/issues/56) [PR #4453](https://github.com/PHPOffice/PhpSpreadsheet/pull/4453)
3435

3536
## 2025-04-16 - 4.2.0
3637

src/PhpSpreadsheet/Cell/Hyperlink.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,11 +68,11 @@ public function setTooltip(string $tooltip): static
6868
}
6969

7070
/**
71-
* Is this hyperlink internal? (to another worksheet).
71+
* Is this hyperlink internal? (to another worksheet or a cell in this worksheet).
7272
*/
7373
public function isInternal(): bool
7474
{
75-
return str_contains($this->url, 'sheet://');
75+
return str_starts_with($this->url, 'sheet://') || str_starts_with($this->url, '#');
7676
}
7777

7878
public function getTypeHyperlink(): string

src/PhpSpreadsheet/Writer/Xls/Worksheet.php

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -467,8 +467,9 @@ public function close(): void
467467
[$column, $row] = Coordinate::indexesFromString($coordinate);
468468

469469
$url = $hyperlink->getUrl();
470-
471-
if (str_contains($url, 'sheet://')) {
470+
if ($url[0] === '#') {
471+
$url = "internal:$url";
472+
} elseif (str_starts_with($url, 'sheet://')) {
472473
// internal to current workbook
473474
$url = str_replace('sheet://', 'internal:', $url);
474475
} elseif (Preg::isMatch('/^(http:|https:|ftp:|mailto:)/', $url)) {
@@ -955,12 +956,11 @@ private function writeUrlRange(int $row1, int $col1, int $row2, int $col2, strin
955956
// Check for internal/external sheet links or default to web link
956957
if (Preg::isMatch('[^internal:]', $url)) {
957958
$this->writeUrlInternal($row1, $col1, $row2, $col2, $url);
958-
}
959-
if (Preg::isMatch('[^external:]', $url)) {
959+
} elseif (Preg::isMatch('[^external:]', $url)) {
960960
$this->writeUrlExternal($row1, $col1, $row2, $col2, $url);
961+
} else {
962+
$this->writeUrlWeb($row1, $col1, $row2, $col2, $url);
961963
}
962-
963-
$this->writeUrlWeb($row1, $col1, $row2, $col2, $url);
964964
}
965965

966966
/**
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace PhpOffice\PhpSpreadsheetTests\Writer\Xls;
6+
7+
use PhpOffice\PhpSpreadsheet\Spreadsheet;
8+
use PhpOffice\PhpSpreadsheetTests\Functional\AbstractFunctional;
9+
10+
class HyperlinkTest extends AbstractFunctional
11+
{
12+
public function testHyperlink(): void
13+
{
14+
$spreadsheet = new Spreadsheet();
15+
$sheet1 = $spreadsheet->getActiveSheet();
16+
$sheet1->setTitle('First');
17+
$sheet2 = $spreadsheet->createSheet();
18+
$sheet2->setTitle('Second');
19+
$sheet2->setCellValue('A100', 'other sheet');
20+
$sheet1->setCellValue('A100', 'this sheet');
21+
$sheet1->setCellValue('A1', '=HYPERLINK("#A100", "here")');
22+
$sheet1->setCellValue('A2', '=HYPERLINK("#Second!A100", "there")');
23+
$sheet1->setCellValue('A3', '=HYPERLINK("http://example.com", "external")');
24+
$sheet1->setCellValue('A4', 'gotoA101');
25+
$sheet1->getCell('A4')
26+
->getHyperlink()
27+
->setUrl('#A101');
28+
29+
$robj = $this->writeAndReload($spreadsheet, 'Xls');
30+
$spreadsheet->disconnectWorksheets();
31+
$sheet0 = $robj->setActiveSheetIndex(0);
32+
self::assertSame('sheet://#A100', $sheet0->getCell('A1')->getHyperlink()->getUrl());
33+
self::assertSame('sheet://#Second!A100', $sheet0->getCell('A2')->getHyperlink()->getUrl());
34+
self::assertSame('http://example.com', $sheet0->getCell('A3')->getHyperlink()->getUrl());
35+
self::assertSame('sheet://#A101', $sheet0->getCell('A4')->getHyperlink()->getUrl());
36+
$robj->disconnectWorksheets();
37+
}
38+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace PhpOffice\PhpSpreadsheetTests\Writer\Xlsx;
6+
7+
use PhpOffice\PhpSpreadsheet\Spreadsheet;
8+
use PhpOffice\PhpSpreadsheetTests\Functional\AbstractFunctional;
9+
10+
class HyperlinkTest extends AbstractFunctional
11+
{
12+
public function testHyperlink(): void
13+
{
14+
$spreadsheet = new Spreadsheet();
15+
$sheet1 = $spreadsheet->getActiveSheet();
16+
$sheet1->setTitle('First');
17+
$sheet2 = $spreadsheet->createSheet();
18+
$sheet2->setTitle('Second');
19+
$sheet2->setCellValue('A100', 'other sheet');
20+
$sheet1->setCellValue('A100', 'this sheet');
21+
$sheet1->setCellValue('A1', '=HYPERLINK("#A100", "here")');
22+
$sheet1->setCellValue('A2', '=HYPERLINK("#Second!A100", "there")');
23+
$sheet1->setCellValue('A3', '=HYPERLINK("http://example.com", "external")');
24+
$sheet1->setCellValue('A4', 'gotoA101');
25+
$sheet1->getCell('A4')
26+
->getHyperlink()
27+
->setUrl('#A101');
28+
29+
$robj = $this->writeAndReload($spreadsheet, 'Xlsx');
30+
$spreadsheet->disconnectWorksheets();
31+
$sheet0 = $robj->setActiveSheetIndex(0);
32+
self::assertSame('sheet://#A100', $sheet0->getCell('A1')->getHyperlink()->getUrl());
33+
self::assertSame('sheet://#Second!A100', $sheet0->getCell('A2')->getHyperlink()->getUrl());
34+
self::assertSame('http://example.com', $sheet0->getCell('A3')->getHyperlink()->getUrl());
35+
self::assertSame('sheet://#A101', $sheet0->getCell('A4')->getHyperlink()->getUrl());
36+
$robj->disconnectWorksheets();
37+
}
38+
}

0 commit comments

Comments
 (0)