AutorÃa | Ultima modificación | Ver Log |
<?php
namespace PhpOffice\PhpSpreadsheet\Style\NumberFormat;
use PhpOffice\PhpSpreadsheet\Calculation\MathTrig;
class FractionFormatter extends BaseFormatter
{
/** @param null|bool|float|int|string $value value to be formatted */
public static function format(mixed $value, string $format): string
{
$format = self::stripQuotes($format);
$value = (float) $value;
$absValue = abs($value);
$sign = ($value < 0.0) ? '-' : '';
$integerPart = floor($absValue);
$decimalPart = self::getDecimal((string) $absValue);
if ($decimalPart === '0') {
return "{$sign}{$integerPart}";
}
$decimalLength = strlen($decimalPart);
$decimalDivisor = 10 ** $decimalLength;
preg_match('/(#?.*\?)\/(\?+|\d+)/', $format, $matches);
$formatIntegerPart = $matches[1] ?? '0';
if (isset($matches[2]) && is_numeric($matches[2])) {
$fractionDivisor = 100 / (int) $matches[2];
} else {
/** @var float $fractionDivisor */
$fractionDivisor = MathTrig\Gcd::evaluate((int) $decimalPart, $decimalDivisor);
}
$adjustedDecimalPart = (int) round((int) $decimalPart / $fractionDivisor, 0);
$adjustedDecimalDivisor = $decimalDivisor / $fractionDivisor;
if ((str_contains($formatIntegerPart, '0'))) {
return "{$sign}{$integerPart} {$adjustedDecimalPart}/{$adjustedDecimalDivisor}";
} elseif ((str_contains($formatIntegerPart, '#'))) {
if ($integerPart == 0) {
return "{$sign}{$adjustedDecimalPart}/{$adjustedDecimalDivisor}";
}
return "{$sign}{$integerPart} {$adjustedDecimalPart}/{$adjustedDecimalDivisor}";
} elseif ((str_starts_with($formatIntegerPart, '? ?'))) {
if ($integerPart == 0) {
$integerPart = '';
}
return "{$sign}{$integerPart} {$adjustedDecimalPart}/{$adjustedDecimalDivisor}";
}
$adjustedDecimalPart += $integerPart * $adjustedDecimalDivisor;
return "{$sign}{$adjustedDecimalPart}/{$adjustedDecimalDivisor}";
}
private static function getDecimal(string $value): string
{
$decimalPart = '0';
if (preg_match('/^\d*[.](\d*[1-9])0*$/', $value, $matches) === 1) {
$decimalPart = $matches[1];
}
return $decimalPart;
}
}