diff --git a/src/ext/spout/SpoutBuilder.php b/src/ext/spout/SpoutBuilder.php
index 5abdade..e45f1e9 100644
--- a/src/ext/spout/SpoutBuilder.php
+++ b/src/ext/spout/SpoutBuilder.php
@@ -14,14 +14,22 @@ use nulib\ref\ext\spout\ref_builder_ods;
 use nulib\ref\ext\spout\ref_builder_xlsx;
 use nulib\str;
 use nulib\web\http;
-use OpenSpout\Common\Entity\Cell;
 use OpenSpout\Common\Entity\Style\Border;
 use OpenSpout\Common\Entity\Style\BorderPart;
+use OpenSpout\Common\Entity\Cell\DateTimeCell;
+use OpenSpout\Common\Entity\Cell\EmptyCell;
+use OpenSpout\Common\Entity\Cell\NumericCell;
+use OpenSpout\Common\Entity\Cell\StringCell;
+use OpenSpout\Common\Entity\Row;
+use OpenSpout\Common\Entity\Style\Color;
 use OpenSpout\Common\Entity\Style\Style;
-use OpenSpout\Common\Helper\CellTypeHelper;
-use OpenSpout\Writer\Common\Creator\WriterEntityFactory;
-use OpenSpout\Writer\WriterMultiSheetsAbstract;
+use OpenSpout\Writer\AbstractWriterMultiSheets;
+use OpenSpout\Writer\Common\AbstractOptions;
+use OpenSpout\Writer\ODS\Options as ODSOptions;
+use OpenSpout\Writer\ODS\Writer as ODSWriter;
 use OpenSpout\Writer\XLSX\Entity\SheetView;
+use OpenSpout\Writer\XLSX\Options as XLSXOptions;
+use OpenSpout\Writer\XLSX\Writer as XLSXWriter;
 
 class SpoutBuilder extends AbstractBuilder {
   use TAbstractBuilder;
@@ -42,16 +50,16 @@ class SpoutBuilder extends AbstractBuilder {
     return $object;
   }
 
-  protected static function add_border_part(?Border &$border, string $name, ?array $params): void {
+  protected static function add_border_part(?array &$parts, string $name, ?array $params): void {
     if ($params === null) return;
-    if ($border === null) $border = new Border();
-    $part = new BorderPart($name);
     if (($color = $params["color"] ?? null) !== null) {
-      $part->setColor(cl::get(ref_builder::COLORS, $color, $color));
+      $color = cl::get(ref_builder::COLORS, $color, $color);
+    } else {
+      $color = Color::BLACK;
     }
-    if (($width = $params["width"] ?? null) !== null) $part->setWidth($width);
-    if (($style = $params["style"] ?? null) !== null) $part->setStyle($style);
-    $border->addPart($part);
+    if (($width = $params["width"] ?? null) === null) $width = Border::WIDTH_MEDIUM;
+    if (($style = $params["style"] ?? null) === null) $style = Border::STYLE_SOLID;
+    $parts[] = new BorderPart($name, $color, $width, $style);
   }
 
   protected static function set_defaults(?array &$params, string $key, array $defaults): void {
@@ -82,8 +90,9 @@ class SpoutBuilder extends AbstractBuilder {
       $style->setBackgroundColor(cl::get(ref_builder::COLORS, $color, $color));
     }
     if (($align = $cell["align"] ?? null) !== null) $style->setCellAlignment($align);
-    //if (($align = $cell["valign"] ?? null) !== null) $style->setCellVerticalAlignment($align);
+    if (($align = $cell["valign"] ?? null) !== null) $style->setCellVerticalAlignment($align);
     if (($wrap = $cell["wrap"] ?? null) !== null) $style->setShouldWrapText($wrap);
+    if (($rotation = $cell["rotation"] ?? null) !== null) $style->setTextRotation($rotation);
     if (($format = $cell["format"] ?? null) !== null) $style->setFormat($format);
     if (($border = $cell["border"] ?? null) !== null) {
       if (is_string($border)) {
@@ -114,18 +123,14 @@ class SpoutBuilder extends AbstractBuilder {
           if ($colorAll !== null) $part["color"] = $colorAll;
         }; unset($part);
       }
-
-      $top = $border["top"] ?? null;
-      $right = $border["right"] ?? null;
-      $bottom = $border["bottom"] ?? null;
-      $left = $border["left"] ?? null;
-      $border = null;
-      self::add_border_part($border, "top", $top);
-      self::add_border_part($border, "right", $right);
-      self::add_border_part($border, "bottom", $bottom);
-      self::add_border_part($border, "left", $left);
-      if ($border !== null) $style->setBorder($border);
+      $parts = null;
+      self::add_border_part($parts, "top", $border["top"] ?? null);
+      self::add_border_part($parts, "right", $border["right"] ?? null);
+      self::add_border_part($parts, "bottom", $border["bottom"] ?? null);
+      self::add_border_part($parts, "left", $border["left"] ?? null);
+      if ($parts !== null) $style->setBorder(new Border(...$parts));
     }
+    if (($autofit = $cell["autofit"] ?? null) !== null) $style->setShouldShrinkToFit($autofit);
     return $style;
   }
 
@@ -173,26 +178,31 @@ class SpoutBuilder extends AbstractBuilder {
     case "ods":
     case self::SS_TYPE_ODS:
       $ssType = self::SS_TYPE_ODS;
-      $ssWriter = WriterEntityFactory::createODSWriter();
-      self::apply_params($ssWriter, $spoutParams, ref_builder_ods::PARAMS_SPOUT);
+      $ssOptions = new ODSOptions();
+      $ssWriterClass = ODSWriter::class;
+      $refParams = ref_builder_ods::PARAMS_SPOUT;
       break;
     case "xlsx":
     case self::SS_TYPE_XLSX:
     default:
-      $ssType = self::SS_TYPE_XLSX;
-      $ssWriter = WriterEntityFactory::createXLSXWriter();
-      self::apply_params($ssWriter, $spoutParams, ref_builder_xlsx::PARAMS_SPOUT);
-      break;
+        $ssType = self::SS_TYPE_XLSX;
+        $ssOptions = new XLSXOptions();
+        $ssWriterClass = XLSXWriter::class;
+        $refParams = ref_builder_xlsx::PARAMS_SPOUT;
+        break;
     }
     $defaultColumnWidth = $spoutParams["default_column_width"] ?? null;
-    if ($defaultColumnWidth !== null) $ssWriter->setDefaultColumnWidth($defaultColumnWidth);
+    if ($defaultColumnWidth !== null) $ssOptions->DEFAULT_COLUMN_WIDTH = $defaultColumnWidth;
     $defaultRowHeight = $spoutParams["default_row_height"] ?? null;
-    if ($defaultRowHeight !== null) $ssWriter->setDefaultRowHeight($defaultRowHeight);
+    if ($defaultRowHeight !== null) $ssOptions->DEFAULT_ROW_HEIGHT = $defaultRowHeight;
     $defaultRowStyle = $spoutParams["default_row_style"] ?? null;
-    if ($defaultRowStyle !== null) $ssWriter->setDefaultRowStyle($defaultRowStyle);
+    if ($defaultRowStyle !== null) $ssOptions->DEFAULT_ROW_STYLE = $defaultRowStyle;
+    self::apply_params($ssOptions, $spoutParams, $refParams);
+    $ssWriter = new $ssWriterClass($ssOptions);
     $ssWriter->writeToStream($this->getResource());
 
     $this->ssType = $ssType;
+    $this->ssOptions = $ssOptions;
     $this->ssWriter = $ssWriter;
     $this->spoutParams = $spoutParams;
     $this->typeNumeric = boolval($params["type_numeric"] ?? static::TYPE_NUMERIC);
@@ -213,7 +223,9 @@ class SpoutBuilder extends AbstractBuilder {
   /** @var int type de fichier généré */
   protected int $ssType;
 
-  protected WriterMultiSheetsAbstract $ssWriter;
+  protected AbstractOptions $ssOptions;
+
+  protected AbstractWriterMultiSheets $ssWriter;
 
   protected ?array $spoutParams;
 
@@ -338,7 +350,8 @@ class SpoutBuilder extends AbstractBuilder {
    * Les lignes sont indexées sur 1
    */
   function mergeCells(int $topLeftCol, int $topLeftRow, int $bottomRightCol, int $bottomRightRow): void {
-    $this->ssWriter->mergeCells([$topLeftCol, $topLeftRow], [$bottomRightCol, $bottomRightRow]);
+    $sheet = $this->ssWriter->getCurrentSheet();
+    $this->ssOptions->mergeCells($topLeftCol, $topLeftRow, $bottomRightCol, $bottomRightRow, $sheet->getIndex());
   }
 
   protected function isNumeric($value): bool {
@@ -356,10 +369,6 @@ class SpoutBuilder extends AbstractBuilder {
       $style ??= new Style();
       $style->setFormat(self::DATETIME_FORMAT);
       return true;
-    } elseif (CellTypeHelper::isDateTimeOrDateInterval($value)) {
-      $style ??= new Style();
-      $style->setFormat(self::DATE_FORMAT);
-      return true;
     }
     if (!is_string($value) || !$this->typeDate) return false;
     if (DateTime::isa_datetime($value, true)) {
@@ -401,16 +410,14 @@ class SpoutBuilder extends AbstractBuilder {
       $style = $colStyles[$key] ?? null;
       self::ensure_style($style);
       if ($col === null || $col === "") {
-        $type = Cell::TYPE_EMPTY;
+        $cell = new EmptyCell(null, $style);
       } elseif ($this->isNumeric($col)) {
-        $type = Cell::TYPE_NUMERIC;
+        $cell = new NumericCell($col, $style);
       } elseif ($this->isDate($col, $style)) {
-        $type = Cell::TYPE_DATE;
+        $cell = new DateTimeCell($col, $style);
       } else {
-        $type = Cell::TYPE_STRING;
+        $cell = new StringCell($col, $style);
       }
-      $cell = WriterEntityFactory::createCell($col, $style);
-      $cell->setType($type);
       $cells[] = $cell;
     }
 
@@ -421,7 +428,7 @@ class SpoutBuilder extends AbstractBuilder {
     }
     $rowStyle ??= $oddStyle;
     self::ensure_style($rowStyle);
-    $row = WriterEntityFactory::createRow($cells, $rowStyle);
+    $row = new Row($cells, $rowStyle);
     self::apply_params($row, $rowParams, ref_builder::ROW_PARAMS);
 
     $mergeCells = $rowParams["merge_cells"] ?? null;
diff --git a/src/ref/ext/spout/ref_builder.php b/src/ref/ext/spout/ref_builder.php
index 9bc7701..e84cfaa 100644
--- a/src/ref/ext/spout/ref_builder.php
+++ b/src/ref/ext/spout/ref_builder.php
@@ -82,6 +82,7 @@ class ref_builder {
     "align" => "string",
     "valign" => "string",
     "wrap" => "bool",
+    "rotation" => "int",
     "format" => "string",
     "border" => [
       "top" => ["color" => "string", "width" => "string", "style" => "string"],
@@ -89,5 +90,6 @@ class ref_builder {
       "bottom" => ["color" => "string", "width" => "string", "style" => "string"],
       "left" => ["color" => "string", "width" => "string", "style" => "string"],
     ],
+    "autofit" => "bool",
   ];
 }
diff --git a/src/ref/ext/spout/ref_builder_xlsx.php b/src/ref/ext/spout/ref_builder_xlsx.php
index 60bd011..fe85dff 100644
--- a/src/ref/ext/spout/ref_builder_xlsx.php
+++ b/src/ref/ext/spout/ref_builder_xlsx.php
@@ -1,16 +1,43 @@
 <?php
 namespace nulib\ref\ext\spout;
 
+use OpenSpout\Writer\XLSX\Options\HeaderFooter;
+use OpenSpout\Writer\XLSX\Options\PageMargin;
+use OpenSpout\Writer\XLSX\Options\PageSetup;
+
 class ref_builder_xlsx extends ref_builder {
+  const PARAMS_SPOUT = [
+   ...parent::PARAMS_SPOUT,
+   "->setPageSetup" => [
+     PageSetup::class,
+     "page_orientation" => "string",
+     "page_size" => "string",
+     "fit_to_height" => "bool",
+     "fit_to_width" => "bool",
+     "page_order" => "string",
+   ],
+   "->setPageMargin" => [
+     PageMargin::class,
+     "top" => "float",
+     "right" => "float",
+     "bottom" => "float",
+     "left" => "float",
+     "header" => "float",
+     "footer" => "float",
+   ],
+   "->setHeaderFooter" => [
+     HeaderFooter::class,
+     "odd_header" => "string",
+     "odd_footer" => "string",
+     "even_header" => "string",
+     "even_footer" => "string",
+     "different_odd_even" => "bool",
+   ],
+  ];
+
   const PARAMS_SHEET = [
+    ...parent::PARAMS_SHEET,
     "view" => self::PARAMS_SHEET_VIEW,
-    # copie de parent::SHEET
-    "->setName" => ["string"],
-    "->setIsVisible" => ["bool"],
-    "header_style" => self::STYLE,
-    "odd_style" => self::STYLE,
-    "even_style" => self::STYLE,
-    "different_odd_even" => "bool",
   ];
 
   const PARAMS_SHEET_VIEW = [