randym / axlsx

xlsx generation with charts, images, automated column width, customizable styles and full schema validation. Axlsx excels at helping you generate beautiful Office Open XML Spreadsheet documents without having to understand the entire ECMA specification. Check out the README for some examples of how easy it is. Best of all, you can validate your xlsx file before serialization so you know for sure that anything generated is going to load on your client's machine.
MIT License
2.62k stars 696 forks source link

Bubble chart support #253

Closed skateinmars closed 11 years ago

skateinmars commented 11 years ago

Hello,

I want to add bubble charts support to Axlsx. This is a type of scatter chart (which is already supported) but has a third value (besides x and y coordinates) that determines the size of the point (named bubbleSize in the XML).

I can't seem to find any readable documentation about this in the spec so for now I'm manually converting a generated scatter chart to a bubble chart in LibreOffice and checking the diff between the two XML chart files. This is incredibly inefficient though. The main change needed seems to be a <c:bubbleSize> that has to be added in the <c:bubbleChart> tag.

On the code side, I'm guessing we need to add a BubbleChart class and maybe a BubbleSeries class? The API should look like this:

chart.add_series xData: sheet["A1:A3"],
                         yData: sheet["B1:B3"],
                         bubbleSize: sheet["C1:C3"]

Am I on the right track here? Do you have any (usable) resource concerning the spec?

Anyway, thanks for this library, this is a great time saver.

randym commented 11 years ago

Hi @skateinmars conceptually you are definitely on the right track. I would suggest having a look at the specification. While the explanations are often less then helpful, the schema declarations are very helpful indeed.

http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-376,%20Fourth%20Edition,%20Part%201%20-%20Fundamentals%20And%20Markup%20Language%20Reference.zip

for example, page 4060 in Part 1 Fundamentals and Markup language reference:

<xsd:complexType name="CT_BubbleChart">
    <xsd:sequence>
       <xsd:element name="varyColors" type="CT_Boolean" minOccurs="0" maxOccurs="1"/>
       <xsd:element name="ser" type="CT_BubbleSer" minOccurs="0" maxOccurs="unbounded"/>
       <xsd:element name="dLbls" type="CT_DLbls" minOccurs="0" maxOccurs="1"/>
       <xsd:element name="bubble3D" type="CT_Boolean" minOccurs="0" maxOccurs="1"/>
       <xsd:element name="bubbleScale" type="CT_BubbleScale" minOccurs="0" maxOccurs="1"/>
       <xsd:element name="showNegBubbles" type="CT_Boolean" minOccurs="0" maxOccurs="1"/>
       <xsd:element name="sizeRepresents" type="CT_SizeRepresents" minOccurs="0" maxOccurs="1"/>
       <xsd:element name="axId" type="CT_UnsignedInt" minOccurs="2" maxOccurs="2"/>
       <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/>
    </xsd:sequence>
</xsd:complexType>
skateinmars commented 11 years ago

Thanks for the tips. I managed to generate a bubble chart, though I didn't include every possible optional elements (bubble3D, bubbleScale...)

Basically the BubbleSeries is almost identical to the ScatterSeries, the change being in the initialize method: @bubbleSize = NumDataSource.new({:tag_name => :bubbleSize, :data => options[:bubbleSize]}) unless options[:bubbleSize].nil?

There is also a small change needed in NumDataSource, and a BubbleChart class.

I'm planning to do a pull request for this, but I'm wondering if my BubbleSeries and BubbleChart classes should inherit from the base Series and Chart classes or I can directly inherit from ScatterSeries/ScatterChart?

randym commented 11 years ago

Hi @skateinmars

Keep at it!!

BubbleChart should definitely inherit from Chart, and generate its own series data as the specification is different.

skateinmars commented 11 years ago

Thanks, the pull request https://github.com/randym/axlsx/pull/254 should be complete now!

randym commented 11 years ago

Sorry mate, I'll try to get to this later tonight. Thanks for your patience.