diff --git a/components/fpspreadsheet/examples/other/chart/bubblechart_write_demo.lpi b/components/fpspreadsheet/examples/other/chart/bubblechart_write_demo.lpi
new file mode 100644
index 000000000..91a9ca97a
--- /dev/null
+++ b/components/fpspreadsheet/examples/other/chart/bubblechart_write_demo.lpi
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<CONFIG>
+  <ProjectOptions>
+    <Version Value="12"/>
+    <PathDelim Value="\"/>
+    <General>
+      <Flags>
+        <MainUnitHasCreateFormStatements Value="False"/>
+        <MainUnitHasTitleStatement Value="False"/>
+        <MainUnitHasScaledStatement Value="False"/>
+      </Flags>
+      <SessionStorage Value="InProjectDir"/>
+      <Title Value="bubblechart_write_demo"/>
+      <UseAppBundle Value="False"/>
+      <ResourceType Value="res"/>
+    </General>
+    <BuildModes>
+      <Item Name="Default" Default="True"/>
+    </BuildModes>
+    <PublishOptions>
+      <Version Value="2"/>
+      <UseFileFilters Value="True"/>
+    </PublishOptions>
+    <RunParams>
+      <FormatVersion Value="2"/>
+    </RunParams>
+    <RequiredPackages>
+      <Item>
+        <PackageName Value="laz_fpspreadsheet"/>
+      </Item>
+    </RequiredPackages>
+    <Units>
+      <Unit>
+        <Filename Value="bubblechart_write_demo.lpr"/>
+        <IsPartOfProject Value="True"/>
+      </Unit>
+    </Units>
+  </ProjectOptions>
+  <CompilerOptions>
+    <Version Value="11"/>
+    <PathDelim Value="\"/>
+    <Target>
+      <Filename Value="bubblechart_write_demo"/>
+    </Target>
+    <SearchPaths>
+      <IncludeFiles Value="$(ProjOutDir)"/>
+      <UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/>
+    </SearchPaths>
+    <Linking>
+      <Debugging>
+        <DebugInfoType Value="dsDwarf3"/>
+      </Debugging>
+    </Linking>
+    <Other>
+      <ConfigFile>
+        <WriteConfigFilePath Value=""/>
+      </ConfigFile>
+    </Other>
+  </CompilerOptions>
+  <Debugging>
+    <Exceptions>
+      <Item>
+        <Name Value="EAbort"/>
+      </Item>
+      <Item>
+        <Name Value="ECodetoolError"/>
+      </Item>
+      <Item>
+        <Name Value="EFOpenError"/>
+      </Item>
+    </Exceptions>
+  </Debugging>
+</CONFIG>
diff --git a/components/fpspreadsheet/examples/other/chart/bubblechart_write_demo.lpr b/components/fpspreadsheet/examples/other/chart/bubblechart_write_demo.lpr
new file mode 100644
index 000000000..407da5a51
--- /dev/null
+++ b/components/fpspreadsheet/examples/other/chart/bubblechart_write_demo.lpr
@@ -0,0 +1,84 @@
+program bubblechart_write_demo;
+
+{.$DEFINE DARK_MODE}
+
+uses
+  SysUtils,
+  fpspreadsheet, fpstypes, fpsUtils, fpschart, xlsxooxml, fpsopendocument;
+
+const
+  FILE_NAME = 'bubble';
+  sDISTANCE = 'Distance from Sun' + LineEnding + '(relative to Earth)';
+  sPERIOD = 'Orbital period' + LineEnding + '(relative to Earth)';
+  sDIAMETER = 'Diameter (km)';
+var
+  book: TsWorkbook;
+  sheet: TsWorksheet;
+  ch: TsChart;
+  ser: TsBubbleSeries;
+begin
+  book := TsWorkbook.Create;
+  try
+    // worksheet
+    sheet := book.AddWorksheet('bubble_series');
+
+    // Enter data
+    sheet.WriteText( 0,0, 'Solar System');
+    sheet.WriteFont( 0,0, '', 12, [fssBold], scBlack);
+
+    sheet.WriteText( 2,0, 'Planet' );  sheet.WriteText  ( 2,1, sDistance);  sheet.WriteText  ( 2,2, sPERIOD);  sheet.WriteText  (2, 3, sDIAMETER);
+    sheet.WriteText( 3,0, 'Mercury');  sheet.WriteNumber( 3,1, 0.387);      sheet.WriteNumber( 3,2,  0.241);   sheet.WriteNumber( 3,3, 4.879E3);
+    sheet.WriteText( 4,0, 'Venus'  );  sheet.WriteNumber( 4,1, 0.723);      sheet.WriteNumber( 4,2,  0.615);   sheet.WriteNumber( 4,3, 1.210E4);
+    sheet.WriteText( 5,0, 'Earth'  );  sheet.WriteNumber( 5,1, 1.000);      sheet.WriteNumber( 5,2,  1.000);   sheet.WriteNumber( 5,3, 1.276E4);
+    sheet.WriteText( 6,0, 'Mars'   );  sheet.WriteNumber( 6,1, 1.524);      sheet.WriteNumber( 6,2,  1.881);   sheet.WriteNumber( 6,3, 6.792E3);
+    sheet.WriteText( 7,0, 'Jupiter');  sheet.WriteNumber( 7,1, 5.204);      sheet.WriteNumber( 7,2, 11.862);   sheet.WriteNumber( 7,3, 1.430E5);
+    sheet.WriteText( 8,0, 'Saturn' );  sheet.WriteNumber( 8,1, 9.582);      sheet.WriteNumber( 8,2, 29.445);   sheet.WriteNumber( 8,3, 1.205E5);
+    sheet.WriteText( 9,0, 'Uranus' );  sheet.WriteNumber( 9,1,19.201);      sheet.WriteNumber( 9,2, 84.011);   sheet.WriteNumber( 9,3, 5.112E4);
+    sheet.WriteText(10,0, 'Neptune');  sheet.WriteNumber(10,1,30.047);      sheet.WriteNumber(10,2,164.79);    sheet.WriteNumber(10,3, 4.953E4);
+
+    sheet.WriteText(12,0, 'Source: wikipedia');
+    sheet.WriteFont(12,0, '', 8, [], scBlack);
+
+    sheet.WriteColWidth(1, 40.0, suMillimeters);
+    sheet.WriteColWidth(2, 40.0, suMillimeters);
+
+    // Create chart: left/top in cell D4, 150 mm x 150 mm
+    ch := book.AddChart(sheet, 2, 4, 150, 150);
+
+    // Chart properties
+    ch.Border.Style := clsNoLine;
+    ch.Title.Caption := 'Solar System';
+    ch.Title.Font.Style := [fssBold];
+    ch.Legend.Visible := false;
+    ch.XAxis.Title.Caption := 'Distance from Sun (relative to Earth)';
+    ch.XAxis.MinorGridLines.Style := clsNoLine;
+    ch.XAxis.Logarithmic := true;
+    ch.YAxis.Title.Caption := 'Orbital period (relative to Earth)';
+    ch.YAxis.AxisLine.Color := scSilver;
+    ch.YAxis.MinorGridLines.Style := clsNoLine;
+    ch.YAxis.Logarithmic := true;
+
+    // Add data as bubble series
+    ser := TsBubbleSeries.Create(ch);
+    ser.SetLabelRange(3, 0, 10, 0);
+    ser.SetXRange(3, 1, 10, 1);
+    ser.SetYRange(3, 2, 10, 2);
+    ser.SetBubbleRange(3, 3, 10, 3);
+    ser.Line.Style := clsNoLine;
+    ser.Fill.Color := $c47244; //72c4 scBlue;
+    ser.Fill.Transparency := 0.25;
+    ser.DataLabels := [cdlCategory];
+    ch.AddSeries(ser);
+
+    {
+    book.WriteToFile(FILE_NAME + '.xlsx', true);   // Excel fails to open the file
+    WriteLn('Data saved with chart in ', FILENAME, '.xlsx');
+    }
+
+    book.WriteToFile(FILE_NAME + '.ods', true);
+    WriteLn('Data saved with chart in ', FILE_NAME, '.ods');
+  finally
+    book.Free;
+  end;
+end.
+
diff --git a/components/fpspreadsheet/examples/visual/fpschart/fpschartlink/main.pas b/components/fpspreadsheet/examples/visual/fpschart/fpschartlink/main.pas
index 7fb91b4fe..251cecc0b 100644
--- a/components/fpspreadsheet/examples/visual/fpschart/fpschartlink/main.pas
+++ b/components/fpspreadsheet/examples/visual/fpschart/fpschartlink/main.pas
@@ -35,7 +35,8 @@ implementation
 {$R *.lfm}
 
 const
-  FILE_NAME = '../../../other/chart/bars.ods';
+//  FILE_NAME = '../../../other/chart/bars.ods';
+  FILE_NAME = '../../../other/chart/bubble.ods';
 //  FILE_NAME = '../../../other/chart/area.ods';
 //  FILE_NAME = '../../../other/chart/area-sameImg.ods';
 //  FILE_NAME = '../../../other/chart/pie.ods';
diff --git a/components/fpspreadsheet/source/common/fpschart.pas b/components/fpspreadsheet/source/common/fpschart.pas
index ee2e9d0fc..a55c13d9a 100644
--- a/components/fpspreadsheet/source/common/fpschart.pas
+++ b/components/fpspreadsheet/source/common/fpschart.pas
@@ -391,6 +391,7 @@ type
   end;
 
   TsBubbleSeries = class(TsChartSeries)
+  // to do: inherited from ScatterSeries, but without symbols
   private
     FBubbleRange: TsChartRange;
   public
@@ -1629,6 +1630,7 @@ begin
   FSubTitle.Font.Size := 12;
 
   FLegend := TsChartLegend.Create(self);
+  FLegend.Visible := false;
 
   FXAxis := TsChartAxis.Create(self);
   FXAxis.Title.Caption := 'x axis';
diff --git a/components/fpspreadsheet/source/visual/fpspreadsheetchart.pas b/components/fpspreadsheet/source/visual/fpspreadsheetchart.pas
index f2c04fa96..d3665d230 100644
--- a/components/fpspreadsheet/source/visual/fpspreadsheetchart.pas
+++ b/components/fpspreadsheet/source/visual/fpspreadsheetchart.pas
@@ -23,7 +23,7 @@ uses
   LCLVersion, Forms, Controls, Graphics, GraphUtil, Dialogs,
   // TAChart
   TATypes, TATextElements, TAChartUtils, TALegend, TACustomSource, TASources,
-  TACustomSeries, TASeries, TARadialSeries, TAFitUtils, TAFuncSeries,
+  TACustomSeries, TASeries, TARadialSeries, TAFitUtils, TAFuncSeries, TAMultiSeries,
   TAChartAxisUtils, TAChartAxis, TAStyles, TAGraph,
   // FPSpreadsheet
   fpsTypes, fpSpreadsheet, fpsUtils, fpsChart,
@@ -140,6 +140,7 @@ type
 
     procedure UpdateAreaSeries(AWorkbookSeries: TsAreaSeries; AChartSeries: TAreaSeries);
     procedure UpdateBarSeries(AWorkbookSeries: TsBarSeries; AChartSeries: TBarSeries);
+    procedure UpdateBubbleSeries(AWorkbookSeries: TsBubbleSeries; AChartSeries: TBubbleSeries);
     procedure UpdateLineSeries(AWorkbookSeries: TsLineSeries; AChartSeries: TLineSeries);
     procedure UpdatePieSeries(AWorkbookSeries: TsPieSeries; AChartSeries: TPieSeries);
     procedure UpdatePolarSeries(AWorkbookSeries: TsRadarSeries; AChartSeries: TPolarSeries);
@@ -830,8 +831,8 @@ begin
     SetLength(FWorksheets[ARangeIndex], Length(FWorksheets[ARangeIndex]) + 1);
 
   case ARangeIndex of
-    rngX: XCount := Length(FRanges[ARangeIndex]);
-    rngY: YCount := Length(FRanges[ARangeIndex]);
+    rngX: XCount := Max(XCount, Length(FRanges[ARangeIndex]));
+    rngY: YCount := Max(YCount, Length(FRanges[ARangeIndex]));
   end;
 
   SetLength(FRanges[ARangeIndex, AListIndex], 1);   // FIXME: Assuming here single-block range !!!
@@ -968,7 +969,7 @@ begin
       if (calcSrc.Origin is TsWorkbookChartSource) then
         src := TsWorkbookChartSource(calcSrc.Origin);
     end else
-    // ... otherwise we use the workbook chartsource directly.
+    // ... otherwise we use the workbook chart source directly.
     if (firstSeries.Source is TsWorkbookChartSource) then
     begin
       src := (firstSeries.Source as TsWorkbookChartSource);
@@ -978,12 +979,14 @@ begin
 
     src.SetYRange(src.YCount, ASeries.YRange);      // <--- This updates also the YCount
     src.FRangeStr[rngY] := src.BuildRangeStr(rngY);
+
     if Result is TBarSeries then
       TBarSeries(Result).Styles := FChartStyles
     else if Result is TLineSeries then
       TLineSeries(Result).Styles := FChartStyles
     else if Result is TAreaSeries then
       TAreaSeries(Result).Styles := FChartStyles;
+
     Result.Legend.Multiplicity := lmStyle;
     src.SetTitleAddr(ASeries.TitleAddr);
 
@@ -997,6 +1000,9 @@ begin
   else
   begin
     // This is either for a non-stackable or the first stackable series.
+    src := TsWorkbookChartSource.Create(self);
+    src.WorkbookSource := FWorkbookSource;
+
     case ASeries.ChartType of
       ctBar:
         Result := TBarSeries.Create(FChart);
@@ -1006,10 +1012,15 @@ begin
         Result := TAreaSeries.Create(FChart);
       ctRadar, ctFilledRadar:
         Result := TPolarSeries.Create(FChart);
+      ctBubble:
+        begin
+          Result := TBubbleSeries.Create(FChart);
+          src.SetYRange(1, TsBubbleSeries(ASeries).BubbleRange);
+        end;
+      else
+        exit(nil);
     end;
 
-    src := TsWorkbookChartSource.Create(self);
-    src.WorkbookSource := FWorkbookSource;
     if not ASeries.LabelRange.IsEmpty then src.SetLabelRange(ASeries.LabelRange);
     if not ASeries.XRange.IsEmpty then src.SetXRange(0, ASeries.XRange);
     if not ASeries.YRange.IsEmpty then src.SetYRange(0, ASeries.YRange);
@@ -1039,6 +1050,12 @@ var
   axis: TsChartAxis;
 begin
   ser := ActiveChartSeries(ASeries);
+  if ser = nil then
+  begin
+    FWorkbook.AddErrorMsg('Series could not be loaded.');
+    exit;
+  end;
+
   ser.Transparency := round(ASeries.Fill.Transparency);
   axis := ASeries.Chart.YAxis;
   UpdateChartSeriesMarks(ASeries, ser);
@@ -1059,6 +1076,8 @@ begin
       UpdateAreaSeries(TsAreaSeries(ASeries), TAreaSeries(ser));
     ctBar:
       UpdateBarSeries(TsBarSeries(ASeries), TBarSeries(ser));
+    ctBubble:
+      UpdateBubbleSeries(TsBubbleSeries(ASeries), TBubbleSeries(ser));
     ctLine:
       UpdateLineSeries(TsLineSeries(ASeries), TLineSeries(ser));
     ctScatter:
@@ -1403,6 +1422,13 @@ begin
     TCalculatedChartSource(AChartSeries.Source).Percentage := (AWorkbookSeries.Chart.StackMode = csmStackedPercentage);
 end;
 
+procedure TsWorkbookChartlink.UpdateBubbleSeries(AWorkbookSeries: TsBubbleSeries;
+  AChartSeries: TBubbleSeries);
+begin
+  UpdateChartBrush(AWorkbookSeries.Chart, AWorkbookSeries.Fill, AChartSeries.BubbleBrush);
+  UpdateChartPen(AWorkbookSeries.Chart, AWorkbookSeries.Line, AChartSeries.BubblePen);
+end;
+
 procedure TsWorkbookChartLink.UpdateChart;
 var
   ch: TsChart;