Bir üretici grafiği yeniden yazdığında, C sütununu göstermesi gereken etiketler çıplak sayılar olarak döner ya da bir çubuk 20.0 yerine S1; 2; 20 okur; oysa Excel dosyayı şikayetsiz açar. Value From Cells etiketleri bir Office 2013 grafik uzantısında oturur; HotXLS bu uzantıyı TXLSXChartSeries.DataLabelsRange üzerinden, şema sırasında nokta başına tam etiket ayarlarıyla yazar
Excel Value From Cells etiketlerini nerede tutar?
ECMA-376 grafik şeması (Bölüm 1, §21.2), bu etiketin metnini bir çalışma sayfası aralığından al anlamına gelen hiçbir element taşımaz. Şemanın CT_DLbls türü, bir serinin içindeki <c:dLbls> bloğu, sayısı belirsiz kadar tek noktalık <c:dLbl> geçersiz kılması taşır; ardından ya <c:delete> ya da paylaşılan etiket grubu gelir ve sonunda bir uzantı listesi durur. Paylaşılan grup sabit bir dizidir: numFmt, spPr, txPr, dLblPos, showLegendKey, showVal, showCatName, showSerName, showPercent, showBubbleSize, separator, showLeaderLines, leaderLines. Excelin Veri Etiketlerini Biçimlendir panosundaki neredeyse her onay kutusu bu elementlerden birine oturur. Value From Cells oturmaz. Excel 2013 bunu, standardın üstüne c15 namespaceindeki (http://schemas.microsoft.com/office/drawing/2012/chart) uzantı listeleriyle ekledi ve Microsoft [MS-ODRAWXML] içinde belgeledi; dolayısıyla ECMA-376 şemasından katı biçimde kurulan bir okuyucu orada opak <c:ext> elementlerinden başka bir şey görmez. Önemli kısımlarına indirgenmiş hâliyle, hücre aralığı etiketli bir seri şöyle görünür:
<c:ser>
<c:idx val="0"/><c:order val="0"/>
<c:tx>...</c:tx>
<c:dLbls>
<!-- sıfır ya da daha fazla <c:dLbl> nokta geçersiz kılması bloğun başında durur -->
<c:showLegendKey val="0"/>
<c:showVal val="1"/>
<c:showCatName val="0"/>
<c:showSerName val="0"/>
<c:showPercent val="0"/>
<c:showBubbleSize val="0"/>
<c:extLst>
<c:ext uri="{CE6537A1-D6FC-4f65-9D91-7224C49458BB}"
xmlns:c15="http://schemas.microsoft.com/office/drawing/2012/chart">
<c15:showDataLabelsRange val="1"/>
</c:ext>
</c:extLst>
</c:dLbls>
<c:cat>...</c:cat>
<c:val>...</c:val>
<c:extLst>
<c:ext uri="{02D57815-91ED-43cb-92C2-25804820EDAC}"
xmlns:c15="http://schemas.microsoft.com/office/drawing/2012/chart">
<c15:datalabelsRange>
<c15:f>Sales!$C$1:$C$3</c15:f>
<c15:dlblRangeCache>
<c:ptCount val="3"/>
<c:pt idx="0"><c:v>Target met</c:v></c:pt>
...
</c15:dlblRangeCache>
</c15:datalabelsRange>
</c:ext>
</c:extLst>
</c:ser>
Özellik iki yere bölünmüş durumda. Aralık seriye aittir: {02D57815-91ED-43cb-92C2-25804820EDAC} URIli seri düzeyi uzantı c15:datalabelsRange taşır; bunun c15:fsi başvuruyu, c15:dlblRangeCachesi ise dosya kaydedildiğinde göründükleri hâliyle etiket metinlerini tutar. Anahtar etiketlere aittir: c15:showDataLabelsRange, <c:dLbls>un sonunda {CE6537A1-D6FC-4f65-9D91-7224C49458BB} URIli bir uzantının içinde oturur ve aynı uzantı, tek bir <c:dLbl>i kapatarak aralık metnini tek nokta için açıp kapayabilir
İki yarım da tek başına düşer. Aralığı olup anahtarı olmayan dosya hiç hücre metni göstermez; anahtarı olup aralığı olmayan dosyanın da gösterecek bir şeyi yoktur. Yalnızca §21.2de tanımlı olanı modelleyen bir program, grafik parçasını yeniden ürettiğinde ikisini de kaybeder; HotXLSin bir düzenlemede modellenmemiş ChartMLi koruması bunun içindir. Önbellek, başvuru kadar önemlidir: aralığı çözümleyemeyen bir tüketici — örneğin aralık başka bir çalışma kitabına işaret ediyordur — yine de çizecek metne ihtiyaç duyar
Bir seriye etiket aralığını ayarlamak
HotXLSte aralık, serinin bir özelliğidir. TXLSXChartSeries.DataLabelsRange atamak aynı zamanda ShowDataLabelsRangeu açar ve onu açıkça kurulmuş olarak işaretler; çünkü anahtarı olmayan bir aralık asla gösterilmez ve boş bir dizge atamak onu yeniden kapatır. Hücre metni, sıradan anahtarlarla (ShowValue, ShowCategoryName, ShowSeriesName, ShowPercent, ShowLegendKey, ShowBubbleSize) birleşir ve Separatorle birleştirilir; LabelNumFmt ise değer kısmını biçimler. Bir eğilim çizgisinin denklem etiketi bu bloğun parçası değildir; <c:trendline>in içinde yaşar ve eğilim çizgisi denklem metni için Excelin kendi kurallarını izler. Grafik kaydedilirken ResolveDataLabelsRange, DataLabelsCachei hücrelerin biçimlendirilmiş metninden tazeler ve grafik yalnızca görünür hücreleri çizerken gizli satır ve sütunları atlar; başka bir çalışma kitabına giden aralık, açıldığı önbelleği korur. Çalışma kitabı ile grafik oluşturma, her zamanki HotXLS grafik kalıbını izler: yeni bir çalışma kitabında siz bir sayfa ekleyene dek sayfa yoktur ve Sheets.Items 1den sayar
uses
lxHandleX;
procedure BuildRevenueChart(const FileName: WideString);
var
Book: TXLSXWorkbook;
Sheet: TXLSXWorksheet;
Chart: TXLSXChart;
Series: TXLSXChartSeries;
begin
Book := TXLSXWorkbook.Create;
try
Sheet := Book.Sheets.Add('Sales');
Sheet.Cells[1, 1].Value := 'East';
Sheet.Cells[1, 2].Value := 18.25;
Sheet.Cells[1, 3].Value := 'Target met';
Sheet.Cells[2, 1].Value := 'Central';
Sheet.Cells[2, 2].Value := 20;
Sheet.Cells[2, 3].Value := 'Restated';
Sheet.Cells[3, 1].Value := 'West';
Sheet.Cells[3, 2].Value := 14.6;
Sheet.Cells[3, 3].Value := 'Below plan';
Chart := Sheet.AddChart(xlsxChartBar, 'Revenue by region', 1, 5, 16, 12);
Series := Chart.AddSeries('Revenue', 'Sales!$A$1:$A$3', 'Sales!$B$1:$B$3');
// Aynı zamanda ShowDataLabelsRange := True yapar ve kurulu olarak işaretler
Series.DataLabelsRange := 'Sales!$C$1:$C$3';
Series.ShowValue := True; // hücre metni artı değer
Series.Separator := ' | ';
Series.LabelNumFmt := '0.0'; // değer kısmı 20.0 okur, 20 değil
Series.LabelPos := xlsxDlblPosOutEnd;
Book.SaveAs(FileName);
finally
Book.Free;
end;
end;
Şemanın ST_DLblPos sabit listesi dokuz konum belirteci sayar ve bunların herhangi birini herhangi bir grafikte kabul eder; dolayısıyla doğrulayıcı, bir çizgi serisindeki outEnde itiraz etmez. Hangi konumların anlamlı olduğu grafik türüne bağlıdır: çubuk ve sütun serileri ctr, inBase, inEnd ile outEnd alır, pasta grafikler bestFit ekler, çizgi ve dağılım serileri ise l, r, t ile b kullanır. HotXLS, seçilen TXLSXChartDataLabelPos değerini kendi belirteci olarak yazar ve hükmü Excelin olana bırakır; LabelPos da grafik türünüze düşen alt kümeden gelmelidir. xlsxDlblPosDefault atamak LabelPosSeti temizler, hiç dLblPos yazmaz ve etiketleri Excelin yerleştirmesine bırakır. Yukarıdaki örnek için Beklenen: her çubuğun, ucunun dışında, hücre metniyle ve bir ondalıklı değeriyle etiketlenmesi; iki kısmın | ile birleştirilmesi
Tek noktalık bir etiket neleri tekrar etmek zorundadır?
Seri etiketinin söylediği her şeyi. Şema, nokta geçersiz kılmasını ucuz gösterir: CT_DLbl bir idxtir; ardından ya delete ya da bir etiket grubu gelir (aynı numFmt ile separator arası dizinin önünde isteğe bağlı bir layout ile tx durur) ve isteğe bağlı bir uzantı listesi eklenir; grubun her üyesi isteğe bağlıdır. Yalnızca idx ile showDataLabelsRange uzantısı taşıyan bir <c:dLbl> bu yüzden şemaya uygundur. Excel böyle bir etiketi 20.0 yerine S1; 2; 20 olarak çizer: atlanan her show* anahtarını açık sayar, seri adıyla kategori görünür ve seri sayı biçimini devralmaz. Bir nokta etiketi, o nokta için seri etiketine yama yapmaz; onu bütün olarak değiştirir; Excelin kendi yazdığı nokta etiketlerinin tam anahtar seti taşıması bu yüzdedir. XMLi küçük tutmak için asgari geçersiz kılmalar veren bir üretici doğrulamayı geçer ve yine de yanlış metin gösterir
HotXLS her nokta etiketini tam bir değiştirme olarak yazar. SetPointShowDataLabelsRange(APointIndex, AVisible), aralık metni için tek noktaya açık ya da kapalı bir değer kaydeder; anahtar, idxe dönüşen 0 tabanlı nokta indeksidir. Kaydetme zamanında böyle her nokta bir <c:dLbl> alır: idx, seri sayı biçimi, konum ve anahtarlar grup sırasıyla ve en son o noktanın değerini taşıyan {CE6537A1-…} uzantısı. SetPointLabelText(APointIndex, AText), <c:tx> üzerinden birebir metin ekler; metni, aralık geçersiz kırması ve korunmuş düzeni olan bir indeks yine de tek bir <c:dLbl> alır. Okuma sırasında seri anahtarları seri düzeyinden alınır; nokta etiketlerinin içindeki kopyalar onları asla ezmez. Aşağıdaki kod gelir serisine iki geçersiz kırma kurar ve ardından gelen XML, nokta 1 için beklenen etikettir
procedure OverridePoints(Series: TXLSXChartSeries);
var
I: Integer;
Visible: Boolean;
begin
// İkinci çubuk (idx 1): yalnızca değeri göster, hücre metni olmadan
Series.SetPointShowDataLabelsRange(1, False);
// Üçüncü çubuk (idx 2): bütün etiketi birebir metinle değiştir
Series.SetPointLabelText(2, 'Q3 pending audit');
for I := 0 to Series.DataLabelRangeOverrideCount - 1 do
Writeln('point ', Series.DataLabelRangeOverrideIndexes[I],
' range text: ', Series.DataLabelRangeOverrideValues[I]);
if Series.TryGetPointShowDataLabelsRange(0, Visible) then
Writeln('point 0 has its own override')
else
Writeln('point 0 follows ShowDataLabelsRange = ',
Series.ShowDataLabelsRange);
end;
<!-- Nokta 1 için beklenen XML -->
<c:dLbl>
<c:idx val="1"/>
<c:numFmt formatCode="0.0" sourceLinked="0"/>
<c:dLblPos val="outEnd"/>
<c:showLegendKey val="0"/>
<c:showVal val="1"/>
<c:showCatName val="0"/>
<c:showSerName val="0"/>
<c:showPercent val="0"/>
<c:showBubbleSize val="0"/>
<c:separator> | </c:separator>
<c:extLst>
<c:ext uri="{CE6537A1-D6FC-4f65-9D91-7224C49458BB}"
xmlns:c15="http://schemas.microsoft.com/office/drawing/2012/chart">
<c15:showDataLabelsRange val="0"/>
</c:ext>
</c:extLst>
</c:dLbl>
Bir grafiği Excelin açması XMLi hakkında az şey kanıtlar
Excel, çocukları sıra dışı olan grafikleri açar; <c:dLbls> içinde bilinmeyen elementler bile olsa özelliklerini doğru geri okur. val="banana" gibi geçersiz bir öznitelik değeri ise Workbooks.Openu düşürür. Öbür tüketiciler daha az hoşgörülüdür. Open XML SDKnin OpenXmlValidatoru sıra dışı çocukları şema hatası olarak bildirir ve şemaya katı bağlanan araçlar onları reddeder; dolayısıyla Excelde çalışan bir grafik, aşağı akışta bir hattı hâlâ bozabilir. Üretilmiş grafik parçalarını OpenXmlValidator ile doğrulayın; Excelde çift tıklamak yalnızca Excelin işi çevirdiğini söyler. Bunlar, §21.2 şemasından gelen en kolay yanlış yapılacak sıra kurallarıdır:
<c:dLbls>içinde nokta geçersiz kılmaları önde durur, paylaşılan grup izler veextLstbloğu kapatır; grubun içindedLblPoshershow*anahtarından önce gelir veshowLegendKey,showValden önce durur- Bir nokta etiketinin içinde
layoutiletx,idxi izler venumFmtten önce gelir; noktanın uzantı listesi onu kapatır - Bir çubuk serisi
idx,order,tx,spPr,invertIfNegative,pictureOptions,dPt,dLbls,trendline,errBars,cat,val,shape,extLstdizilir; bir çizgi serisi, çubuk serisinininvertIfNegativeilepictureOptionstaşıdığı yerdemarker,shapetaşıdığı yerde isesmoothbulundurur - Dağılım, alan ve balon serileri aynı iskeleti korur (etiketler, eğilim çizgileri, hata çubukları ve veri, bu sırayla) ama kendi üyeleriyle: dağılım ve balon verisi için
xValileyVal; bir balon serisinde veriden sonrabubbleSizeilebubble3D - Seri düzeyinde alışılmış sürçmeler,
dLblsten önce yazılan veri başvuruları,trendlineden önce gelenerrBarsile veriden önce gelensmoothtur; Excel bunların hiçbirinden şikayet etmez
Elle konumlanan etiketler nokta etiketine yazılır
Düzen, sezginin şemadan ayrıldığı yerdir. Bir kullanıcı Excelde bir etiketi sürüklediğinde, elle konum o etiketin <c:dLbl>sinin içinde, idxin hemen ardından <c:layout> olarak saklanır. CT_DLblsin layout çocuğu yoktur; dolayısıyla bütün seti konumlandıracağını umarak doğrudan <c:dLbls>in altına bir tane yazan üretici, doğrulayıcının geçersiz çocuk diye işaretlediği bir dosya üretir. Excel o dosyayı açar ve kimsenin istemediği bir şey yapar: düzeni yalnızca ilk etikete uygular, onu bir idx 0 nokta düzeninin koyacağı yere koyar ve kalan etiketlerin genişliklerini yanlış okur; 37.7lik bir etiket genişliği 52.3 olarak döner. Grafik neredeyse doğru görünür; bu da hatanın gözden kaçmasını kolaylaştırır
Bir uzantıdan kopyalanan bir düzen, bütün çalışma kitabını okunmaz kılabilir. Excel bir c15:layoutu bir etiketin uzantı listesinin içinde de tutabilir ve c15 öneki, parçanın üzerinde değil onu saran <c:ext>in üzerinde bildirilir. Düzenleri yerel ada göre bulan kod o elementi de yakalar ve onu <c:dLbls>in içine yapıştırmak öneki bildirimi olmadan taşır; böylece yeniden kurulan grafik parçası bildirilmemiş bir namespace öneki barındırır ve namespace farkında hiçbir XML ayrıştırıcısı onu yüklemez. Düzenleri namespace ile ve doğrudan çocuk konumuyla eşleştirin; asla yalnızca yerel adla değil
HotXLS bir etiket düzenini yalnızca <c:dLbls>in ya da bir <c:dLbl>in doğrudan <c:layout> çocuğundan alır; asla bir uzantının içinden almaz ve nokta indeksiyle anahtarlayarak birebir saklar. LabelLayoutXml ilk etiketin düzenini tutar; doğrudan <c:dLbls>in altında bulunan başıboş bir tane dâhil, çünkü Excel onu öyle yorumlar. PointLabelLayoutCount, PointLabelLayoutIndexes ile PointLabelLayoutXmls kalanları sayar. Grafik yeniden üretilirken o düzen, idx 0 <c:dLbl>ine gider ve her öteki düzen kendi indeksinin <c:dLbl>ine; her biri o noktanın aralık geçersiz kırmasıyla ve metniyle tek bir etikette birleşir
procedure ReportLabelLayouts(const FileName: WideString);
var
Book: TXLSXWorkbook;
Sheet: TXLSXWorksheet;
Series: TXLSXChartSeries;
C, S, I: Integer;
begin
Book := TXLSXWorkbook.Create;
try
if Book.Open(FileName) <> 1 then
Exit;
Sheet := Book.Sheets[1]; // 1 tabanlı sayfa indeksi
for C := 0 to Sheet.Charts.Count - 1 do
for S := 0 to Sheet.Charts[C].SeriesCount - 1 do
begin
Series := Sheet.Charts[C].Series[S];
Writeln('chart ', C, ' series ', S,
' label range: ', Series.DataLabelsRange,
' cached texts: ', Series.DataLabelsCache.Count);
if Series.LabelLayoutXml <> '' then
Writeln(' first label has a manual layout');
for I := 0 to Series.PointLabelLayoutCount - 1 do
Writeln(' point ', Series.PointLabelLayoutIndexes[I],
' layout: ', Series.PointLabelLayoutXmls[I]);
end;
finally
Book.Free;
end;
end;
Excel bir nokta etiketini bütün bir etiket olarak okur; dolayısıyla onu öyle yazmak — elle konumu aynı <c:dLbl>in üzerine koyarak — hem S1; 2; 20 metnini hem kaymış ilk etiketi grafiklerinizin dışında tutar. HotXLSte bu model, DataLabelsRangein, nokta geçersiz kılma çağrılarının ve korunan düzen özelliklerinin arkasındadır