function makeChartType(chartType, data, opts, valAxisId, catAxisId, isMultiTypeChart) {
		// NOTE: "Chart Range" (as shown in "select Chart Area dialog") is calculated.
		// ....: Ensure each X/Y Axis/Col has same row height (esp. applicable to XY Scatter where X can often be larger than Y's)
		var strXml = '';

		switch ( chartType ) {
			case 'area':
			case 'bar':
			case 'bar3D':
			case 'line':
			case 'radar':
				// 1: Start Chart
				strXml += '<c:'+ chartType +'Chart>';
				if ( chartType == 'bar' || chartType == 'bar3D' ) {
					strXml += '<c:barDir val="'+ opts.barDir +'"/>';
					strXml += '<c:grouping val="'+ opts.barGrouping +'"/>';
				}

				if ( chartType == 'radar' ) {
					strXml += '<c:radarStyle val="'+ opts.radarStyle +'"/>';
				}

				strXml += '<c:varyColors val="0"/>';

				// 2: "Series" block for every data row
				/* EX:
					data: [
				     {
				       name: 'Region 1',
				       labels: ['April', 'May', 'June', 'July'],
				       values: [17, 26, 53, 96]
				     },
				     {
				       name: 'Region 2',
				       labels: ['April', 'May', 'June', 'July'],
				       values: [55, 43, 70, 58]
				     }
				    ]
				*/
				var colorIndex = -1; // Maintain the color index by region
				data.forEach(function(obj){
					colorIndex++;
					var idx = obj.index;
					strXml += '<c:ser>';
					strXml += '  <c:idx val="'+ idx +'"/>';
					strXml += '  <c:order val="'+ idx +'"/>';
					strXml += '  <c:tx>';
					strXml += '    <c:strRef>';
					strXml += '      <c:f>Sheet1!$'+ getExcelColName(idx+1) +'$1</c:f>';
					strXml += '      <c:strCache><c:ptCount val="1"/><c:pt idx="0"><c:v>'+ encodeXmlEntities(obj.name) +'</c:v></c:pt></c:strCache>';
					strXml += '    </c:strRef>';
					strXml += '  </c:tx>';
					strXml += '  <c:invertIfNegative val="0"/>';

					// Fill and Border
					var strSerColor = opts.chartColors[colorIndex % opts.chartColors.length];

					strXml += '  <c:spPr>';
					if ( strSerColor == 'transparent' ) {
						strXml += '<a:noFill/>';
					}
					else if ( opts.chartColorsOpacity ) {
						strXml += '<a:solidFill>'+ createColorElement(strSerColor, '<a:alpha val="'+opts.chartColorsOpacity+'000"/>') +'</a:solidFill>';
					}
					else {
						strXml += '<a:solidFill>'+ createColorElement(strSerColor) +'</a:solidFill>';
					}

					if ( chartType == 'line' ) {
						if ( opts.lineSize == 0) {
							strXml += '<a:ln><a:noFill/></a:ln>';
						}
						else {
							strXml += '<a:ln w="' + (opts.lineSize * ONEPT) + '" cap="flat"><a:solidFill>' + createColorElement(strSerColor) + '</a:solidFill>';
							strXml += '<a:prstDash val="' + (opts.lineDash || "solid") + '"/><a:round/></a:ln>';
						}
					}
					else if ( opts.dataBorder ) {
						strXml += '<a:ln w="'+ (opts.dataBorder.pt * ONEPT) +'" cap="flat"><a:solidFill>'+ createColorElement(opts.dataBorder.color) +'</a:solidFill><a:prstDash val="solid"/><a:round/></a:ln>';
					}

					strXml += createShadowElement(opts.shadow, DEF_SHAPE_SHADOW);

					strXml += '  </c:spPr>';

                    // Data Labels per series
					// [20190117] NOTE: Adding these to RADAR chart causes unrecoverable corruption!
					if ( chartType != 'radar' ) {
                        strXml += '  <c:dLbls>';
                        strXml += '    <c:numFmt formatCode="'+ opts.dataLabelFormatCode +'" sourceLinked="0"/>';
                        if ( opts.dataLabelBkgrdColors ) {
							strXml += '    <c:spPr>';
							strXml += '       <a:solidFill>'+ createColorElement(strSerColor) +'</a:solidFill>';
							strXml += '    </c:spPr>';
                        }
                        strXml += '    <c:txPr>';
                        strXml += '      <a:bodyPr/>';
                        strXml += '      <a:lstStyle/>';
                        strXml += '      <a:p><a:pPr>';
                        strXml += '        <a:defRPr b="0" i="0" strike="noStrike" sz="'+ (opts.dataLabelFontSize || DEF_FONT_SIZE) +'00" u="none">';
                        strXml += '          <a:solidFill>'+ createColorElement(opts.dataLabelColor || DEF_FONT_COLOR) +'</a:solidFill>';
                        strXml += '          <a:latin typeface="'+ (opts.dataLabelFontFace || 'Arial') +'"/>';
                        strXml += '        </a:defRPr>';
                        strXml += '      </a:pPr></a:p>';
                        strXml += '    </c:txPr>';
                        // Setting dLblPos tag for bar3D seems to break the generated chart
                        if ( chartType != 'area' && chartType != 'bar3D' ) {
                            strXml += '<c:dLblPos val="'+ (opts.dataLabelPosition || 'outEnd') +'"/>';
                        }
                        strXml += '    <c:showLegendKey val="0"/>';
                        strXml += '    <c:showVal val="'+ (opts.showValue ? '1' : '0') +'"/>';
                        strXml += '    <c:showCatName val="0"/>';
                        strXml += '    <c:showSerName val="0"/>';
                        strXml += '    <c:showPercent val="0"/>';
                        strXml += '    <c:showBubbleSize val="0"/>';
                        strXml += '    <c:showLeaderLines val="0"/>';
                        strXml += '  </c:dLbls>';
                    }

					// 'c:marker' tag: `lineDataSymbol`
					if ( chartType == 'line' || chartType == 'radar') {
						strXml += '<c:marker>';
						strXml += '  <c:symbol val="'+ opts.lineDataSymbol +'"/>';
						if ( opts.lineDataSymbolSize ) {
							// Defaults to "auto" otherwise (but this is usually too small, so there is a default)
							strXml += '  <c:size val="'+ opts.lineDataSymbolSize +'"/>';
						}
						strXml += '  <c:spPr>';
						strXml += '    <a:solidFill>' + createColorElement(opts.chartColors[(idx+1 > opts.chartColors.length ? (Math.floor(Math.random() * opts.chartColors.length)) : idx)]) +'</a:solidFill>';

						var symbolLineColor = opts.lineDataSymbolLineColor || strSerColor;
						strXml += '    <a:ln w="' + opts.lineDataSymbolLineSize + '" cap="flat"><a:solidFill>'+ createColorElement(symbolLineColor) +'</a:solidFill><a:prstDash val="solid"/><a:round/></a:ln>';
						strXml += '    <a:effectLst/>';
						strXml += '  </c:spPr>';
						strXml += '</c:marker>';
					}

					// Color chart bars various colors
					// Allow users with a single data set to pass their own array of colors (check for this using != ours)
					if ( ( chartType == 'bar' || chartType == 'bar3D' ) && ( data.length === 1 || opts.valueBarColors ) && opts.chartColors != BARCHART_COLORS ) {
						// Series Data Point colors
						obj.values.forEach(function(value,index){
							var arrColors = (value < 0 ? (opts.invertedColors || BARCHART_COLORS) : opts.chartColors);

							strXml += '  <c:dPt>';
							strXml += '    <c:idx val="'+ index +'"/>';
							strXml += '      <c:invertIfNegative val="'+ (opts.invertedColors ? 0 : 1) +'"/>';
							strXml += '    <c:bubble3D val="0"/>';
							strXml += '    <c:spPr>';
							if ( opts.lineSize === 0 ){
								strXml += '<a:ln><a:noFill/></a:ln>';
							}
							else if (chartType === 'bar') {
								strXml += '<a:solidFill>';
								strXml += '  <a:srgbClr val="'+ arrColors[index % arrColors.length] +'"/>';
								strXml += '</a:solidFill>';
							}
							else {
								strXml += '<a:ln>';
								strXml += '  <a:solidFill>';
								strXml += '   <a:srgbClr val="'+ arrColors[index % arrColors.length] +'"/>';
								strXml += '  </a:solidFill>';
								strXml += '</a:ln>';
							}
							strXml += createShadowElement(opts.shadow, DEF_SHAPE_SHADOW);
							strXml += '    </c:spPr>';
							strXml += '  </c:dPt>';
						});
					}

					// 2: "Categories"
					{
						strXml += '<c:cat>';
						if ( opts.catLabelFormatCode ) {
							// Use 'numRef' as catLabelFormatCode implies that we are expecting numbers here
							strXml += '  <c:numRef>';
							strXml += '    <c:f>Sheet1!'+ '$A$2:$A$'+ (obj.labels.length+1) +'</c:f>';
							strXml += '    <c:numCache>';
							strXml += '      <c:formatCode>'+ opts.catLabelFormatCode +'</c:formatCode>';
							strXml += '      <c:ptCount val="'+ obj.labels.length +'"/>';
							obj.labels.forEach(function(label,idx){ strXml += '<c:pt idx="'+ idx +'"><c:v>'+ encodeXmlEntities(label) +'</c:v></c:pt>'; });
							strXml += '    </c:numCache>';
							strXml += '  </c:numRef>';
						}
						else {
							strXml += '  <c:strRef>';
							strXml += '    <c:f>Sheet1!'+ '$A$2:$A$'+ (obj.labels.length+1) +'</c:f>';
							strXml += '    <c:strCache>';
							strXml += '	     <c:ptCount val="'+ obj.labels.length +'"/>';
							obj.labels.forEach(function(label,idx){ strXml += '<c:pt idx="'+ idx +'"><c:v>'+ encodeXmlEntities(label) +'</c:v></c:pt>'; });
							strXml += '    </c:strCache>';
							strXml += '  </c:strRef>';
						}
						strXml += '</c:cat>';
					}

					// 3: "Values"
					{
						strXml += '  <c:val>';
						strXml += '    <c:numRef>';
						strXml += '      <c:f>Sheet1!'+ '$'+ getExcelColName(idx+1) +'$2:$'+ getExcelColName(idx+1) +'$'+ (obj.labels.length+1) +'</c:f>';
						strXml += '      <c:numCache>';
						strXml += '        <c:formatCode>General</c:formatCode>';
						strXml += '	       <c:ptCount val="'+ obj.labels.length +'"/>';
						obj.values.forEach(function(value,idx){ strXml += '<c:pt idx="'+ idx +'"><c:v>'+ (value || value == 0 ? value : '') +'</c:v></c:pt>'; });
						strXml += '      </c:numCache>';
						strXml += '    </c:numRef>';
						strXml += '  </c:val>';
					}

					// Option: `smooth`
					if ( chartType == 'line' ) strXml += '<c:smooth val="'+ (opts.lineSmooth ? "1" : "0" ) +'"/>';

					// 4: Close "SERIES"
					strXml += '</c:ser>';
				});

				// 3: "Data Labels"
				{
					strXml += '  <c:dLbls>';
					strXml += '    <c:numFmt formatCode="'+ opts.dataLabelFormatCode +'" sourceLinked="0"/>';
					strXml += '    <c:txPr>';
					strXml += '      <a:bodyPr/>';
					strXml += '      <a:lstStyle/>';
					strXml += '      <a:p><a:pPr>';
					strXml += '        <a:defRPr b="'+ (opts.dataLabelFontBold ? 1 : 0) +'" i="0" strike="noStrike" sz="'+ (opts.dataLabelFontSize || DEF_FONT_SIZE) +'00" u="none">';
					strXml += '          <a:solidFill>'+ createColorElement(opts.dataLabelColor || DEF_FONT_COLOR) +'</a:solidFill>';
					strXml += '          <a:latin typeface="'+ (opts.dataLabelFontFace || 'Arial') +'"/>';
					strXml += '        </a:defRPr>';
					strXml += '      </a:pPr></a:p>';
					strXml += '    </c:txPr>';
					// NOTE: Throwing an error while creating a multi type chart which contains area chart as the below line appears for the other chart type.
					// Either the given change can be made or the below line can be removed to stop the slide containing multi type chart with area to crash.
					if ( opts.type.name != 'area' && opts.type.name != 'radar' && !isMultiTypeChart) strXml += '<c:dLblPos val="'+ (opts.dataLabelPosition || 'outEnd') +'"/>';
					strXml += '    <c:showLegendKey val="0"/>';
					strXml += '    <c:showVal val="'+ (opts.showValue ? '1' : '0') +'"/>';
					strXml += '    <c:showCatName val="0"/>';
					strXml += '    <c:showSerName val="0"/>';
					strXml += '    <c:showPercent val="0"/>';
					strXml += '    <c:showBubbleSize val="0"/>';
					strXml += '    <c:showLeaderLines val="0"/>';
					strXml += '  </c:dLbls>';
				}

				// 4: Add more chart options (gapWidth, line Marker, etc.)
				if ( chartType == 'bar' ) {
					strXml += '  <c:gapWidth val="'+ opts.barGapWidthPct +'"/>';
					strXml += '  <c:overlap val="'+ (opts.barGrouping.indexOf('tacked') > -1 ? 100 : 0) +'"/>';
				}
				else if ( chartType == 'bar3D' ) {
					strXml += '  <c:gapWidth val="'+ opts.barGapWidthPct +'"/>';
					strXml += '  <c:gapDepth val="'+ opts.barGapDepthPct +'"/>';
					strXml += '  <c:shape val="'+ opts.bar3DShape +'"/>';
				}
				else if ( chartType == 'line' ) {
					strXml += '  <c:marker val="1"/>';
				}

				// 5: Add axisId (NOTE: order matters! (category comes first))
				strXml += '  <c:axId val="'+ catAxisId +'"/>';
				strXml += '  <c:axId val="'+ valAxisId +'"/>';
				strXml += '  <c:axId val="'+ AXIS_ID_SERIES_PRIMARY +'"/>';

				// 6: Close Chart tag
				strXml += '</c:'+ chartType +'Chart>';

				// end switch
				break;

			case 'scatter':
				/*
					`data` = [
						{ name:'X-Axis',    values:[1,2,3,4,5,6,7,8,9,10,11,12] },
						{ name:'Y-Value 1', values:[13, 20, 21, 25] },
						{ name:'Y-Value 2', values:[ 1,  2,  5,  9] }
					];
				*/

				// 1: Start Chart
				strXml += '<c:'+ chartType +'Chart>';
				strXml += '<c:scatterStyle val="lineMarker"/>';
				strXml += '<c:varyColors val="0"/>';

				// 2: Series: (One for each Y-Axis)
				var colorIndex = -1;
				data.filter(function(obj,idx){ return idx > 0; }).forEach(function(obj,idx){
					colorIndex++;
					strXml += '<c:ser>';
					strXml += '  <c:idx val="'+ idx +'"/>';
					strXml += '  <c:order val="'+ idx +'"/>';
					strXml += '  <c:tx>';
					strXml += '    <c:strRef>';
					strXml += '      <c:f>Sheet1!$'+ LETTERS[(idx+1)] +'$1</c:f>';
					strXml += '      <c:strCache><c:ptCount val="1"/><c:pt idx="0"><c:v>'+ obj.name +'</c:v></c:pt></c:strCache>';
					strXml += '    </c:strRef>';
					strXml += '  </c:tx>';

					// 'c:spPr': Fill, Border, Line, LineStyle (dash, etc.), Shadow
					strXml += '  <c:spPr>';
					{
						var strSerColor = opts.chartColors[colorIndex % opts.chartColors.length];

						if ( strSerColor == 'transparent' ) {
							strXml += '<a:noFill/>';
						}
						else if ( opts.chartColorsOpacity ) {
							strXml += '<a:solidFill>'+ createColorElement(strSerColor, '<a:alpha val="'+opts.chartColorsOpacity+'000"/>') +'</a:solidFill>';
						}
						else {
							strXml += '<a:solidFill>'+ createColorElement(strSerColor) +'</a:solidFill>';
						}

						if ( opts.lineSize == 0) {
							strXml += '<a:ln><a:noFill/></a:ln>';
						}
						else {
							strXml += '<a:ln w="' + (opts.lineSize * ONEPT) + '" cap="flat"><a:solidFill>' + createColorElement(strSerColor) + '</a:solidFill>';
							strXml += '<a:prstDash val="' + (opts.lineDash || "solid") + '"/><a:round/></a:ln>';
						}

						// Shadow
						strXml += createShadowElement(opts.shadow, DEF_SHAPE_SHADOW);
					}
					strXml += '  </c:spPr>';

					// 'c:marker' tag: `lineDataSymbol`
					{
						strXml += '<c:marker>';
						strXml += '  <c:symbol val="'+ opts.lineDataSymbol +'"/>';
						if ( opts.lineDataSymbolSize ) {
							// Defaults to "auto" otherwise (but this is usually too small, so there is a default)
							strXml += '  <c:size val="'+ opts.lineDataSymbolSize +'"/>';
						}
						strXml += '  <c:spPr>';
						strXml += '    <a:solidFill>' + createColorElement(opts.chartColors[(idx+1 > opts.chartColors.length ? (Math.floor(Math.random() * opts.chartColors.length)) : idx)]) +'</a:solidFill>';
						var symbolLineColor = opts.lineDataSymbolLineColor || strSerColor;
						strXml += '    <a:ln w="' + opts.lineDataSymbolLineSize + '" cap="flat"><a:solidFill>'+ createColorElement(symbolLineColor) +'</a:solidFill><a:prstDash val="solid"/><a:round/></a:ln>';
						strXml += '    <a:effectLst/>';
						strXml += '  </c:spPr>';
						strXml += '</c:marker>';
					}

					// Option: scatter data point labels
					if ( opts.showLabel ) {
						var chartUuid = getUuid('-xxxx-xxxx-xxxx-xxxxxxxxxxxx')
						if ( obj.labels && (opts.dataLabelFormatScatter == 'custom' || opts.dataLabelFormatScatter == 'customXY') ) {
							strXml +='<c:dLbls>';
							obj.labels.forEach(function(label,idx) {
								if ( opts.dataLabelFormatScatter == 'custom' || opts.dataLabelFormatScatter == 'customXY' ) {
									strXml +='  <c:dLbl>';
									strXml +='    <c:idx val="'+idx+'"/>';
									strXml +='    <c:tx>';
									strXml +='      <c:rich>';
									strXml +='			<a:bodyPr>';
									strXml +='				<a:spAutoFit/>';
									strXml +='			</a:bodyPr>';
									strXml +='        	<a:lstStyle/>';
									strXml +='        	<a:p>';
									strXml +='				<a:pPr>'
									strXml +='					<a:defRPr/>'
									strXml +='				</a:pPr>'
									strXml +='          	<a:r>';
									strXml +='            		<a:rPr lang="'+ (opts.lang || 'en-US') +'" dirty="0"/>';
									strXml +='            		<a:t>'+ encodeXmlEntities(label) +'</a:t>';
									strXml +='          	</a:r>';
									// Apply XY values at end of custom label
									// Do not apply the values if the label was empty or just spaces
									// This allows for selective labelling where required
									if ( opts.dataLabelFormatScatter == 'customXY' && !(/^ *$/.test(label)) ) {
										strXml +='          	<a:r>';
										strXml +='          		<a:rPr lang="'+ (opts.lang || 'en-US') +'" baseline="0" dirty="0"/>';
										strXml +='          		<a:t> (</a:t>';
										strXml +='          	</a:r>';
										strXml +='          	<a:fld id="{' + getUuid('xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx') + '}" type="XVALUE">';
										strXml +='          		<a:rPr lang="'+ (opts.lang || 'en-US') +'" baseline="0"/>';
										strXml +='          		<a:pPr>';
										strXml +='          			<a:defRPr/>';
										strXml +='          		</a:pPr>';
										strXml +='          		<a:t>[' + encodeXmlEntities(obj.name) + '</a:t>';
										strXml +='          	</a:fld>';
										strXml +='          	<a:r>';
										strXml +='          		<a:rPr lang="'+ (opts.lang || 'en-US') +'" baseline="0" dirty="0"/>';
										strXml +='          		<a:t>, </a:t>';
										strXml +='          	</a:r>';
										strXml +='          	<a:fld id="{' + getUuid('xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx') + '}" type="YVALUE">';
										strXml +='          		<a:rPr lang="'+ (opts.lang || 'en-US') +'" baseline="0"/>';
										strXml +='          		<a:pPr>';
										strXml +='          			<a:defRPr/>';
										strXml +='          		</a:pPr>';
										strXml +='          		<a:t>[' + encodeXmlEntities(obj.name) + ']</a:t>';
										strXml +='          	</a:fld>';
										strXml +='          	<a:r>';
										strXml +='          		<a:rPr lang="'+ (opts.lang || 'en-US') +'" baseline="0" dirty="0"/>';
										strXml +='          		<a:t>)</a:t>';
										strXml +='          	</a:r>';
										strXml +='          	<a:endParaRPr lang="'+ (opts.lang || 'en-US') +'" dirty="0"/>';
									}
									strXml +='        	</a:p>';
									strXml +='      </c:rich>';
									strXml +='    </c:tx>';
									strXml +='    <c:spPr>';
									strXml +='    	<a:noFill/>';
									strXml +='    	<a:ln>';
									strXml +='    		<a:noFill/>';
									strXml +='    	</a:ln>';
									strXml +='    	<a:effectLst/>';
									strXml +='    </c:spPr>';
									strXml +='    <c:showLegendKey val="0"/>';
									strXml +='    <c:showVal val="0"/>';
									strXml +='    <c:showCatName val="0"/>';
									strXml +='    <c:showSerName val="0"/>';
									strXml +='    <c:showPercent val="0"/>';
									strXml +='    <c:showBubbleSize val="0"/>';
									strXml +='	  <c:showLeaderLines val="1"/>';
									strXml +='    <c:extLst>';
									strXml +='      <c:ext uri="{CE6537A1-D6FC-4f65-9D91-7224C49458BB}" xmlns:c15="http://schemas.microsoft.com/office/drawing/2012/chart">';
									strXml +='			<c15:dlblFieldTable/>';
									strXml +='			<c15:showDataLabelsRange val="0"/>';
									strXml +='		</c:ext>';
									strXml +='      <c:ext uri="{C3380CC4-5D6E-409C-BE32-E72D297353CC}" xmlns:c16="http://schemas.microsoft.com/office/drawing/2014/chart">';
									strXml +='			<c16:uniqueId val="{' + "00000000".substring(0,8-(idx+1).toString().length).toString() + (idx+1) + chartUuid + '}"/>';
									strXml +='      </c:ext>';
									strXml +='		</c:extLst>';
									strXml +='</c:dLbl>';
								}
							});
							strXml +='</c:dLbls>';
						}
						if ( opts.dataLabelFormatScatter == 'XY' ) {
							strXml +='<c:dLbls>';
							strXml +='	<c:spPr>';
							strXml +='		<a:noFill/>';
							strXml +='		<a:ln>';
							strXml +='			<a:noFill/>';
							strXml +='		</a:ln>';
							strXml +='	  	<a:effectLst/>';
							strXml +='	</c:spPr>';
							strXml +='	<c:txPr>';
							strXml +='		<a:bodyPr>';
							strXml +='			<a:spAutoFit/>';
							strXml +='		</a:bodyPr>';
							strXml +='		<a:lstStyle/>';
							strXml +='		<a:p>';
							strXml +='	    	<a:pPr>';
							strXml +='        		<a:defRPr/>';
							strXml +='	    	</a:pPr>';
							strXml +='	    	<a:endParaRPr lang="en-US"/>';
							strXml +='		</a:p>';
							strXml +='	</c:txPr>';
							strXml +='	<c:showLegendKey val="0"/>';
							strXml +='	<c:showVal val="'+ opts.showLabel ? "1" : "0" + '"/>';
							strXml +='	<c:showCatName val="'+ opts.showLabel ? "1" : "0" + '"/>';
							strXml +='	<c:showSerName val="0"/>';
							strXml +='	<c:showPercent val="0"/>';
							strXml +='	<c:showBubbleSize val="0"/>';
							strXml +='	<c:extLst>';
							strXml +='		<c:ext uri="{CE6537A1-D6FC-4f65-9D91-7224C49458BB}" xmlns:c15="http://schemas.microsoft.com/office/drawing/2012/chart">';
							strXml +='			<c15:showLeaderLines val="1"/>';
							strXml +='		</c:ext>';
							strXml +='	</c:extLst>';
							strXml +='</c:dLbls>';
						}
					}

					// Color bar chart bars various colors
					// Allow users with a single data set to pass their own array of colors (check for this using != ours)
					if (( data.length === 1 || opts.valueBarColors ) && opts.chartColors != BARCHART_COLORS ) {
						// Series Data Point colors
						obj.values.forEach(function(value,index){
							var arrColors = (value < 0 ? (opts.invertedColors || BARCHART_COLORS) : opts.chartColors);

							strXml += '  <c:dPt>';
							strXml += '    <c:idx val="'+ index +'"/>';
							strXml += '      <c:invertIfNegative val="'+ (opts.invertedColors ? 0 : 1) +'"/>';
							strXml += '    <c:bubble3D val="0"/>';
							strXml += '    <c:spPr>';
							if ( opts.lineSize === 0 ){
								strXml += '<a:ln><a:noFill/></a:ln>';
							}
							else {
								strXml += '<a:solidFill>';
								strXml += ' <a:srgbClr val="'+ arrColors[index % arrColors.length] +'"/>';
								strXml += '</a:solidFill>';
							}
							strXml += createShadowElement(opts.shadow, DEF_SHAPE_SHADOW);
							strXml += '    </c:spPr>';
							strXml += '  </c:dPt>';
						});
					}

					// 3: "Values": Scatter Chart has 2: `xVal` and `yVal`
					{
						// X-Axis is always the same
						strXml += '<c:xVal>';
						strXml += '  <c:numRef>';
						strXml += '    <c:f>Sheet1!$A$2:$A$'+ (data[0].values.length+1) +'</c:f>';
						strXml += '    <c:numCache>';
						strXml += '      <c:formatCode>General</c:formatCode>';
						strXml += '      <c:ptCount val="'+ data[0].values.length +'"/>';
						data[0].values.forEach(function(value,idx){ strXml += '<c:pt idx="'+ idx +'"><c:v>'+ (value || value == 0 ? value : '') +'</c:v></c:pt>'; });
						strXml += '    </c:numCache>';
						strXml += '  </c:numRef>';
						strXml += '</c:xVal>';

						// Y-Axis vals are this object's `values`
						strXml += '<c:yVal>';
						strXml += '  <c:numRef>';
						strXml += '    <c:f>Sheet1!$'+ getExcelColName(idx+1) +'$2:$'+ getExcelColName(idx+1) +'$'+ (data[0].values.length+1) +'</c:f>';
						strXml += '    <c:numCache>';
						strXml += '      <c:formatCode>General</c:formatCode>';
						// NOTE: Use pt count and iterate over data[0] (X-Axis) as user can have more values than data (eg: timeline where only first few months are populated)
						strXml += '      <c:ptCount val="'+ data[0].values.length +'"/>';
						data[0].values.forEach(function(value,idx){ strXml += '<c:pt idx="'+ idx +'"><c:v>'+ (obj.values[idx] || obj.values[idx] == 0 ? obj.values[idx] : '') +'</c:v></c:pt>'; });
						strXml += '    </c:numCache>';
						strXml += '  </c:numRef>';
						strXml += '</c:yVal>';
					}

					// Option: `smooth`
					strXml += '<c:smooth val="'+ (opts.lineSmooth ? "1" : "0" ) +'"/>';

					// 4: Close "SERIES"
					strXml += '</c:ser>';
				});

				// 3: Data Labels
				{
					strXml += '  <c:dLbls>';
					strXml += '    <c:numFmt formatCode="' + opts.dataLabelFormatCode + '" sourceLinked="0"/>';
					strXml += '    <c:txPr>';
					strXml += '      <a:bodyPr/>';
					strXml += '      <a:lstStyle/>';
					strXml += '      <a:p><a:pPr>';
					strXml += '        <a:defRPr b="0" i="0" strike="noStrike" sz="' + (opts.dataLabelFontSize || DEF_FONT_SIZE) + '00" u="none">';
					strXml += '          <a:solidFill>' + createColorElement(opts.dataLabelColor || DEF_FONT_COLOR) + '</a:solidFill>';
					strXml += '          <a:latin typeface="' + (opts.dataLabelFontFace || 'Arial') + '"/>';
					strXml += '        </a:defRPr>';
					strXml += '      </a:pPr></a:p>';
					strXml += '    </c:txPr>';
					strXml += '    <c:dLblPos val="' + (opts.dataLabelPosition || 'outEnd') + '"/>';
					strXml += '    <c:showLegendKey val="0"/>';
					strXml += '    <c:showVal val="' + (opts.showValue ? '1' : '0') + '"/>';
					strXml += '    <c:showCatName val="0"/>';
					strXml += '    <c:showSerName val="0"/>';
					strXml += '    <c:showPercent val="0"/>';
					strXml += '    <c:showBubbleSize val="0"/>';
					strXml += '  </c:dLbls>';
				}

				// 4: Add axisId (NOTE: order matters! (category comes first))
				strXml += '  <c:axId val="'+ catAxisId +'"/>';
				strXml += '  <c:axId val="'+ valAxisId +'"/>';

				// 5: Close Chart tag
				strXml += '</c:'+ chartType +'Chart>';

				// end switch
				break;

			case 'bubble':
				/*
					`data` = [
						{ name:'X-Axis',     values:[1,2,3,4,5,6,7,8,9,10,11,12] },
						{ name:'Y-Values 1', values:[13, 20, 21, 25], sizes:[10, 5, 20, 15] },
						{ name:'Y-Values 2', values:[ 1,  2,  5,  9], sizes:[ 5, 3,  9,  3] }
					];
				*/

				// 1: Start Chart
				strXml += '<c:'+ chartType +'Chart>';
				strXml += '<c:varyColors val="0"/>';

				// 2: Series: (One for each Y-Axis)
				var colorIndex = -1;
				var idxColLtr = 1;
				data.filter(function(obj,idx){ return idx > 0; }).forEach(function(obj,idx){
					colorIndex++;
					strXml += '<c:ser>';
					strXml += '  <c:idx val="'+ idx +'"/>';
					strXml += '  <c:order val="'+ idx +'"/>';

					// A: `<c:tx>`
					strXml += '  <c:tx>';
					strXml += '    <c:strRef>';
					strXml += '      <c:f>Sheet1!$'+ LETTERS[idxColLtr] +'$1</c:f>';
					strXml += '      <c:strCache><c:ptCount val="1"/><c:pt idx="0"><c:v>'+ obj.name +'</c:v></c:pt></c:strCache>';
					strXml += '    </c:strRef>';
					strXml += '  </c:tx>';

					// B: '<c:spPr>': Fill, Border, Line, LineStyle (dash, etc.), Shadow
					{
						strXml += '<c:spPr>';

						var strSerColor = opts.chartColors[colorIndex % opts.chartColors.length];

						if ( strSerColor == 'transparent' ) {
							strXml += '<a:noFill/>';
						}
						else if ( opts.chartColorsOpacity ) {
							strXml += '<a:solidFill>'+ createColorElement(strSerColor, '<a:alpha val="'+opts.chartColorsOpacity+'000"/>') +'</a:solidFill>';
						}
						else {
							strXml += '<a:solidFill>'+ createColorElement(strSerColor) +'</a:solidFill>';
						}

						if ( opts.lineSize == 0) {
							strXml += '<a:ln><a:noFill/></a:ln>';
						}
						else if ( opts.dataBorder ) {
							strXml += '<a:ln w="'+ (opts.dataBorder.pt * ONEPT) +'" cap="flat"><a:solidFill>'+ createColorElement(opts.dataBorder.color) +'</a:solidFill><a:prstDash val="solid"/><a:round/></a:ln>';
						}
						else {
							strXml += '<a:ln w="' + (opts.lineSize * ONEPT) + '" cap="flat"><a:solidFill>' + createColorElement(strSerColor) + '</a:solidFill>';
							strXml += '<a:prstDash val="' + (opts.lineDash || "solid") + '"/><a:round/></a:ln>';
						}

						// Shadow
						strXml += createShadowElement(opts.shadow, DEF_SHAPE_SHADOW);

						strXml += '</c:spPr>';
					}

					// C: '<c:dLbls>' "Data Labels"
					// Let it be defaulted for now

					// D: '<c:xVal>'/'<c:yVal>' "Values": Scatter Chart has 2: `xVal` and `yVal`
					{
						// X-Axis is always the same
						strXml += '<c:xVal>';
						strXml += '  <c:numRef>';
						strXml += '    <c:f>Sheet1!$A$2:$A$'+ (data[0].values.length+1) +'</c:f>';
						strXml += '    <c:numCache>';
						strXml += '      <c:formatCode>General</c:formatCode>';
						strXml += '      <c:ptCount val="'+ data[0].values.length +'"/>';
						data[0].values.forEach(function(value,idx){ strXml += '<c:pt idx="'+ idx +'"><c:v>'+ (value || value == 0 ? value : '') +'</c:v></c:pt>'; });
						strXml += '    </c:numCache>';
						strXml += '  </c:numRef>';
						strXml += '</c:xVal>';

						// Y-Axis vals are this object's `values`
						strXml += '<c:yVal>';
						strXml += '  <c:numRef>';
						strXml += '    <c:f>Sheet1!$'+ getExcelColName(idxColLtr) +'$2:$'+ getExcelColName(idxColLtr) +'$'+ (data[0].values.length+1) +'</c:f>';
						idxColLtr++;
						strXml += '    <c:numCache>';
						strXml += '      <c:formatCode>General</c:formatCode>';
						// NOTE: Use pt count and iterate over data[0] (X-Axis) as user can have more values than data (eg: timeline where only first few months are populated)
						strXml += '      <c:ptCount val="'+ data[0].values.length +'"/>';
						data[0].values.forEach(function(value,idx){ strXml += '<c:pt idx="'+ idx +'"><c:v>'+ (obj.values[idx] || obj.values[idx] == 0 ? obj.values[idx] : '') +'</c:v></c:pt>'; });
						strXml += '    </c:numCache>';
						strXml += '  </c:numRef>';
						strXml += '</c:yVal>';
					}

					// E: '<c:bubbleSize>'
					strXml += '  <c:bubbleSize>';
					strXml += '    <c:numRef>';
					strXml += '      <c:f>Sheet1!'+ '$'+ getExcelColName(idxColLtr) +'$2:$'+ getExcelColName(idx+2) +'$'+ (obj.sizes.length+1) +'</c:f>';
					idxColLtr++;
					strXml += '      <c:numCache>';
					strXml += '        <c:formatCode>General</c:formatCode>';
					strXml += '	       <c:ptCount val="'+ obj.sizes.length +'"/>';
					obj.sizes.forEach(function(value,idx){ strXml += '<c:pt idx="'+ idx +'"><c:v>'+ (value || '') +'</c:v></c:pt>'; });
					strXml += '      </c:numCache>';
					strXml += '    </c:numRef>';
					strXml += '  </c:bubbleSize>';
					strXml += '  <c:bubble3D val="0"/>';

					// F: Close "SERIES"
					strXml += '</c:ser>';
				});

				// 3: Data Labels
				{
					strXml += '  <c:dLbls>';
					strXml += '    <c:numFmt formatCode="' + opts.dataLabelFormatCode + '" sourceLinked="0"/>';
					strXml += '    <c:txPr>';
					strXml += '      <a:bodyPr/>';
					strXml += '      <a:lstStyle/>';
					strXml += '      <a:p><a:pPr>';
					strXml += '        <a:defRPr b="0" i="0" strike="noStrike" sz="' + (opts.dataLabelFontSize || DEF_FONT_SIZE) + '00" u="none">';
					strXml += '          <a:solidFill>' + createColorElement(opts.dataLabelColor || DEF_FONT_COLOR) + '</a:solidFill>';
					strXml += '          <a:latin typeface="' + (opts.dataLabelFontFace || 'Arial') + '"/>';
					strXml += '        </a:defRPr>';
					strXml += '      </a:pPr></a:p>';
					strXml += '    </c:txPr>';
					strXml += '    <c:dLblPos val="ctr"/>';
					strXml += '    <c:showLegendKey val="0"/>';
					strXml += '    <c:showVal val="' + (opts.showValue ? '1' : '0') + '"/>';
					strXml += '    <c:showCatName val="0"/>';
					strXml += '    <c:showSerName val="0"/>';
					strXml += '    <c:showPercent val="0"/>';
					strXml += '    <c:showBubbleSize val="0"/>';
					strXml += '  </c:dLbls>';
				}

				// 4: Add bubble options
				//strXml += '  <c:bubbleScale val="100"/>';
				//strXml += '  <c:showNegBubbles val="0"/>';
				// Commented out to let it default to PPT until we create options

				// 5: Add axisId (NOTE: order matters! (category comes first))
				strXml += '  <c:axId val="'+ catAxisId +'"/>';
				strXml += '  <c:axId val="'+ valAxisId +'"/>';

				// 6: Close Chart tag
				strXml += '</c:'+ chartType +'Chart>';

				// end switch
				break;

			case 'pie':
			case 'doughnut':
				// Use the same var name so code blocks from barChart are interchangeable
				var obj = data[0];

				/* EX:
					data: [
					 {
					   name: 'Project Status',
					   labels: ['Red', 'Amber', 'Green', 'Unknown'],
					   values: [10, 20, 38, 2]
					 }
					]
				*/

				// 1: Start Chart
				strXml += '<c:'+ chartType +'Chart>';
				strXml += '  <c:varyColors val="0"/>';
				strXml += '<c:ser>';
				strXml += '  <c:idx val="0"/>';
				strXml += '  <c:order val="0"/>';
				strXml += '  <c:tx>';
				strXml += '    <c:strRef>';
				strXml += '      <c:f>Sheet1!$B$1</c:f>';
				strXml += '      <c:strCache>';
				strXml += '        <c:ptCount val="1"/>';
				strXml += '        <c:pt idx="0"><c:v>'+ encodeXmlEntities(obj.name) +'</c:v></c:pt>';
				strXml += '      </c:strCache>';
				strXml += '    </c:strRef>';
				strXml += '  </c:tx>';
				strXml += '  <c:spPr>';
				strXml += '    <a:solidFill><a:schemeClr val="accent1"/></a:solidFill>';
				strXml += '    <a:ln w="9525" cap="flat"><a:solidFill><a:srgbClr val="F9F9F9"/></a:solidFill><a:prstDash val="solid"/><a:round/></a:ln>';
				if ( opts.dataNoEffects ) {
					strXml += '<a:effectLst/>';
				}
				else {
					strXml += createShadowElement(opts.shadow, DEF_SHAPE_SHADOW);
				}
				strXml += '  </c:spPr>';
				strXml += '<c:explosion val="0"/>';

				// 2: "Data Point" block for every data row
				obj.labels.forEach(function(label,idx){
					strXml += '<c:dPt>';
					strXml += '  <c:idx val="'+ idx +'"/>';
					strXml += '  <c:explosion val="0"/>';
					strXml += '  <c:spPr>';
					strXml += '    <a:solidFill>'+ createColorElement(opts.chartColors[(idx+1 > opts.chartColors.length ? (Math.floor(Math.random() * opts.chartColors.length)) : idx)]) +'</a:solidFill>';
					if ( opts.dataBorder ) {
						strXml += '<a:ln w="'+ (opts.dataBorder.pt * ONEPT) +'" cap="flat"><a:solidFill>'+ createColorElement(opts.dataBorder.color) +'</a:solidFill><a:prstDash val="solid"/><a:round/></a:ln>';
					}
					strXml += createShadowElement(opts.shadow, DEF_SHAPE_SHADOW);
					strXml += '  </c:spPr>';
					strXml += '</c:dPt>';
				});

				// 3: "Data Label" block for every data Label
				strXml += '<c:dLbls>';
				obj.labels.forEach(function(label,idx){
					strXml += '<c:dLbl>';
					strXml += '  <c:idx val="'+ idx +'"/>';
					strXml += '    <c:numFmt formatCode="'+ opts.dataLabelFormatCode +'" sourceLinked="0"/>';
					strXml += '    <c:txPr>';
					strXml += '      <a:bodyPr/><a:lstStyle/>';
					strXml += '      <a:p><a:pPr>';
					strXml += '        <a:defRPr b="'+ (opts.dataLabelFontBold ? 1 : 0) +'" i="0" strike="noStrike" sz="'+ (opts.dataLabelFontSize || DEF_FONT_SIZE) +'00" u="none">';
					strXml += '          <a:solidFill>'+ createColorElement(opts.dataLabelColor || DEF_FONT_COLOR) +'</a:solidFill>';
					strXml += '          <a:latin typeface="'+ (opts.dataLabelFontFace || 'Arial') +'"/>';
					strXml += '        </a:defRPr>';
					strXml += '      </a:pPr></a:p>';
					strXml += '    </c:txPr>';
					if (chartType == 'pie') {
						strXml += '    <c:dLblPos val="'+ (opts.dataLabelPosition || 'inEnd') +'"/>';
					}
					strXml += '    <c:showLegendKey val="0"/>';
					strXml += '    <c:showVal val="'+ (opts.showValue ? "1" : "0") +'"/>';
					strXml += '    <c:showCatName val="'+ (opts.showLabel ? "1" : "0") +'"/>';
					strXml += '    <c:showSerName val="0"/>';
					strXml += '    <c:showPercent val="'+ (opts.showPercent ? "1" : "0") +'"/>';
					strXml += '    <c:showBubbleSize val="0"/>';
					strXml += '  </c:dLbl>';
				});
				strXml += '<c:numFmt formatCode="'+ opts.dataLabelFormatCode +'" sourceLinked="0"/>\
		            <c:txPr>\
		              <a:bodyPr/>\
		              <a:lstStyle/>\
		              <a:p>\
		                <a:pPr>\
		                  <a:defRPr b="0" i="0" strike="noStrike" sz="1800" u="none">\
		                    <a:solidFill><a:srgbClr val="000000"/></a:solidFill><a:latin typeface="Arial"/>\
		                  </a:defRPr>\
		                </a:pPr>\
		              </a:p>\
		            </c:txPr>\
		            ' + (chartType == 'pie' ? '<c:dLblPos val="ctr"/>' : '') + '\
		            <c:showLegendKey val="0"/>\
		            <c:showVal val="0"/>\
		            <c:showCatName val="1"/>\
		            <c:showSerName val="0"/>\
		            <c:showPercent val="1"/>\
		            <c:showBubbleSize val="0"/>\
		            <c:showLeaderLines val="0"/>';
				strXml += '</c:dLbls>';

				// 2: "Categories"
				strXml += '<c:cat>';
				strXml += '  <c:strRef>';
				strXml += '    <c:f>Sheet1!'+ '$A$2:$A$'+ (obj.labels.length+1) +'</c:f>';
				strXml += '    <c:strCache>';
				strXml += '	     <c:ptCount val="'+ obj.labels.length +'"/>';
				obj.labels.forEach(function(label,idx){ strXml += '<c:pt idx="'+ idx +'"><c:v>'+ encodeXmlEntities(label) +'</c:v></c:pt>'; });
				strXml += '    </c:strCache>';
				strXml += '  </c:strRef>';
				strXml += '</c:cat>';

				// 3: Create vals
				strXml += '  <c:val>';
				strXml += '    <c:numRef>';
				strXml += '      <c:f>Sheet1!'+ '$B$2:$B$'+ (obj.labels.length+1) +'</c:f>';
				strXml += '      <c:numCache>';
				strXml += '	       <c:ptCount val="'+ obj.labels.length +'"/>';
				obj.values.forEach(function(value,idx){ strXml += '<c:pt idx="'+ idx +'"><c:v>'+ (value || value == 0 ? value : '') +'</c:v></c:pt>'; });
				strXml += '      </c:numCache>';
				strXml += '    </c:numRef>';
				strXml += '  </c:val>';

				// 4: Close "SERIES"
				strXml += '  </c:ser>';
				strXml += '  <c:firstSliceAng val="0"/>';
				if ( chartType == 'doughnut' ) strXml += '  <c:holeSize val="' + (opts.holeSize || 50) + '"/>';
				strXml += '</c:'+ chartType +'Chart>';

				// Done with Doughnut/Pie
				break;
		}

		return strXml;
	}
Create XML string for any given chart type
@example: <c:bubbleChart> or <c:lineChart>

@param {String} CHART_TYPES key
@param {String} data
@param {String} opts
@param {String} valAxisId
@param {String} catAxisId