fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / sc / source / ui / StatisticsDialogs / AnalysisOfVarianceDialog.cxx
blob6a7467d16fb7f2a3e657662571d6b21379b7d87b
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 */
11 #include <sfx2/dispatch.hxx>
12 #include <svl/zforlist.hxx>
13 #include <svl/undo.hxx>
15 #include "formulacell.hxx"
16 #include "rangelst.hxx"
17 #include "scitems.hxx"
18 #include "docsh.hxx"
19 #include "document.hxx"
20 #include "uiitems.hxx"
21 #include "reffact.hxx"
22 #include "strload.hxx"
23 #include "docfunc.hxx"
24 #include "StatisticsDialogs.hrc"
25 #include "TableFillingAndNavigationTools.hxx"
27 #include "AnalysisOfVarianceDialog.hxx"
29 namespace
32 struct StatisticCalculation {
33 sal_Int16 aLabelId;
34 const char* aFormula;
35 const char* aResultRangeName;
38 static StatisticCalculation lclBasicStatistics[] =
40 { STR_ANOVA_LABEL_GROUPS, NULL, NULL },
41 { STRID_CALC_COUNT, "=COUNT(%RANGE%)", "COUNT_RANGE" },
42 { STRID_CALC_SUM, "=SUM(%RANGE%)", "SUM_RANGE" },
43 { STRID_CALC_MEAN, "=AVERAGE(%RANGE%)", "MEAN_RANGE" },
44 { STRID_CALC_VARIANCE, "=VAR(%RANGE%)", "VAR_RANGE" },
45 { 0, NULL, NULL }
48 static sal_Int16 lclAnovaLabels[] =
50 STR_ANOVA_LABEL_SOURCE_OF_VARIATION,
51 STR_ANOVA_LABEL_SS,
52 STR_ANOVA_LABEL_DF,
53 STR_ANOVA_LABEL_MS,
54 STR_ANOVA_LABEL_F,
55 STR_ANOVA_LABEL_P_VALUE,
56 STR_ANOVA_LABEL_F_CRITICAL,
60 static const char strWildcardRange[] = "%RANGE%";
61 static const char strWildcardNumber[] = "%NUMBER%";
63 OUString lclCreateMultiParameterFormula(
64 ScRangeList& aRangeList, const OUString& aFormulaTemplate,
65 const OUString& aWildcard, ScDocument* pDocument,
66 ScAddress::Details& aAddressDetails)
68 OUString aResult;
69 for (size_t i = 0; i < aRangeList.size(); i++)
71 OUString aRangeString(aRangeList[i]->Format(SCR_ABS, pDocument, aAddressDetails));
72 OUString aFormulaString = aFormulaTemplate.replaceAll(aWildcard, aRangeString);
73 aResult += aFormulaString;
74 if(i != aRangeList.size() - 1) // Not Last
75 aResult+= ";";
77 return aResult;
80 void lclMakeSubRangesList(ScRangeList& rRangeList, ScRange& rInputRange, ScStatisticsInputOutputDialog::GroupedBy aGroupedBy)
82 boost::scoped_ptr<DataRangeIterator> pIterator;
83 if (aGroupedBy == ScStatisticsInputOutputDialog::BY_COLUMN)
84 pIterator.reset(new DataRangeByColumnIterator(rInputRange));
85 else
86 pIterator.reset(new DataRangeByRowIterator(rInputRange));
88 for( ; pIterator->hasNext(); pIterator->next() )
90 ScRange aRange = pIterator->get();
91 rRangeList.Append(aRange);
97 ScAnalysisOfVarianceDialog::ScAnalysisOfVarianceDialog(
98 SfxBindings* pSfxBindings, SfxChildWindow* pChildWindow,
99 vcl::Window* pParent, ScViewData* pViewData ) :
100 ScStatisticsInputOutputDialog(
101 pSfxBindings, pChildWindow, pParent, pViewData,
102 "AnalysisOfVarianceDialog", "modules/scalc/ui/analysisofvariancedialog.ui" ),
103 meFactor(SINGLE_FACTOR)
105 get(mpAlphaField, "alpha-spin");
106 get(mpSingleFactorRadio, "radio-single-factor");
107 get(mpTwoFactorRadio, "radio-two-factor");
108 get(mpRowsPerSampleField, "rows-per-sample-spin");
110 mpSingleFactorRadio->SetToggleHdl( LINK( this, ScAnalysisOfVarianceDialog, FactorChanged ) );
111 mpTwoFactorRadio->SetToggleHdl( LINK( this, ScAnalysisOfVarianceDialog, FactorChanged ) );
113 mpSingleFactorRadio->Check(true);
114 mpTwoFactorRadio->Check(false);
116 FactorChanged(NULL);
119 ScAnalysisOfVarianceDialog::~ScAnalysisOfVarianceDialog()
121 disposeOnce();
124 void ScAnalysisOfVarianceDialog::dispose()
126 mpAlphaField.clear();
127 mpSingleFactorRadio.clear();
128 mpTwoFactorRadio.clear();
129 mpRowsPerSampleField.clear();
130 ScStatisticsInputOutputDialog::dispose();
133 bool ScAnalysisOfVarianceDialog::Close()
135 return DoClose( ScAnalysisOfVarianceDialogWrapper::GetChildWindowId() );
138 sal_Int16 ScAnalysisOfVarianceDialog::GetUndoNameId()
140 return STR_ANALYSIS_OF_VARIANCE_UNDO_NAME;
143 IMPL_LINK_NOARG( ScAnalysisOfVarianceDialog, FactorChanged )
145 if (mpSingleFactorRadio->IsChecked())
147 mpGroupByRowsRadio->Enable(true);
148 mpGroupByColumnsRadio->Enable(true);
149 mpRowsPerSampleField->Enable(false);
150 meFactor = SINGLE_FACTOR;
152 else if (mpTwoFactorRadio->IsChecked())
154 mpGroupByRowsRadio->Enable(false);
155 mpGroupByColumnsRadio->Enable(false);
156 mpRowsPerSampleField->Enable(false); // Rows per sample not yet implemented
157 meFactor = TWO_FACTOR;
160 return 0;
163 void ScAnalysisOfVarianceDialog::RowColumn(ScRangeList& rRangeList, AddressWalkerWriter& aOutput, FormulaTemplate& aTemplate,
164 OUString& sFormula, GroupedBy aGroupedBy, ScRange* pResultRange)
166 if (pResultRange != NULL)
167 pResultRange->aStart = aOutput.current();
168 if (!sFormula.isEmpty())
170 for (size_t i = 0; i < rRangeList.size(); i++)
172 ScRange* pRange = rRangeList[i];
173 aTemplate.setTemplate(sFormula);
174 aTemplate.applyRange(strWildcardRange, *pRange);
175 aOutput.writeFormula(aTemplate.getTemplate());
176 if (pResultRange != NULL)
177 pResultRange->aEnd = aOutput.current();
178 aOutput.nextRow();
181 else
183 sal_Int16 aLabelId = (aGroupedBy == BY_COLUMN) ? STR_COLUMN_LABEL_TEMPLATE : STR_ROW_LABEL_TEMPLATE;
184 OUString aLabelTemplate(SC_STRLOAD(RID_STATISTICS_DLGS, aLabelId));
186 for (size_t i = 0; i < rRangeList.size(); i++)
188 aTemplate.setTemplate(aLabelTemplate);
189 aTemplate.applyNumber(strWildcardNumber, i + 1);
190 aOutput.writeString(aTemplate.getTemplate());
191 if (pResultRange != NULL)
192 pResultRange->aEnd = aOutput.current();
193 aOutput.nextRow();
198 void ScAnalysisOfVarianceDialog::AnovaSingleFactor(AddressWalkerWriter& output, FormulaTemplate& aTemplate)
200 output.writeBoldString(SC_STRLOAD(RID_STATISTICS_DLGS, STR_ANOVA_SINGLE_FACTOR_LABEL));
201 output.newLine();
203 double aAlphaValue = mpAlphaField->GetValue() / 100.0;
204 output.writeString(SC_STRLOAD(RID_STATISTICS_DLGS, STR_LABEL_ALPHA));
205 output.nextColumn();
206 output.writeValue(aAlphaValue);
207 aTemplate.autoReplaceAddress("%ALPHA%", output.current());
208 output.newLine();
209 output.newLine();
211 // Write labels
212 for(sal_Int32 i = 0; lclBasicStatistics[i].aLabelId != 0; i++)
214 output.writeString(SC_STRLOAD(RID_STATISTICS_DLGS, lclBasicStatistics[i].aLabelId));
215 output.nextColumn();
217 output.newLine();
219 // Collect aRangeList
220 ScRangeList aRangeList;
221 lclMakeSubRangesList(aRangeList, mInputRange, mGroupedBy);
223 output.push();
225 // Write values
226 for(sal_Int32 i = 0; lclBasicStatistics[i].aLabelId != 0; i++)
228 output.resetRow();
229 ScRange aResultRange;
230 OUString sFormula = OUString::createFromAscii(lclBasicStatistics[i].aFormula);
231 RowColumn(aRangeList, output, aTemplate, sFormula, mGroupedBy, &aResultRange);
232 output.nextColumn();
233 if (lclBasicStatistics[i].aResultRangeName != NULL)
235 OUString sResultRangeName = OUString::createFromAscii(lclBasicStatistics[i].aResultRangeName);
236 aTemplate.autoReplaceRange("%" + sResultRangeName + "%", aResultRange);
240 output.nextRow(); // Blank row
242 // Write ANOVA labels
243 output.resetColumn();
244 for(sal_Int32 i = 0; lclAnovaLabels[i] != 0; i++)
246 output.writeString(SC_STRLOAD(RID_STATISTICS_DLGS, lclAnovaLabels[i]));
247 output.nextColumn();
249 output.nextRow();
251 aTemplate.autoReplaceRange("%FIRST_COLUMN%", *aRangeList[0]);
253 // Between Groups
255 // Label
256 output.resetColumn();
257 output.writeString(SC_STRLOAD(RID_STATISTICS_DLGS, STR_ANOVA_LABEL_BETWEEN_GROUPS));
258 output.nextColumn();
260 // Sum of Squares
262 aTemplate.setTemplate("=SUMPRODUCT(%SUM_RANGE%;%MEAN_RANGE%)-SUM(%SUM_RANGE%)^2/SUM(%COUNT_RANGE%)");
263 aTemplate.autoReplaceAddress("%BETWEEN_SS%", output.current());
264 output.writeFormula(aTemplate.getTemplate());
265 output.nextColumn();
267 // Degree of freedom
268 aTemplate.setTemplate("=COUNT(%SUM_RANGE%)-1");
269 aTemplate.autoReplaceAddress("%BETWEEN_DF%", output.current());
270 output.writeFormula(aTemplate.getTemplate());
271 output.nextColumn();
273 // MS
274 aTemplate.setTemplate("=%BETWEEN_SS% / %BETWEEN_DF%");
275 aTemplate.autoReplaceAddress("%BETWEEN_MS%", output.current());
276 output.writeFormula(aTemplate.getTemplate());
277 output.nextColumn();
279 // F
280 aTemplate.setTemplate("=%BETWEEN_MS% / %WITHIN_MS%");
281 aTemplate.applyAddress("%WITHIN_MS%", output.current(-1, 1));
282 aTemplate.autoReplaceAddress("%F_VAL%", output.current());
283 output.writeFormula(aTemplate.getTemplate());
284 output.nextColumn();
286 // P-value
287 aTemplate.setTemplate("=FDIST(%F_VAL%; %BETWEEN_DF%; %WITHIN_DF%");
288 aTemplate.applyAddress("%WITHIN_DF%", output.current(-3, 1));
289 output.writeFormula(aTemplate.getTemplate());
290 output.nextColumn();
292 // F critical
293 aTemplate.setTemplate("=FINV(%ALPHA%; %BETWEEN_DF%; %WITHIN_DF%");
294 aTemplate.applyAddress("%WITHIN_DF%", output.current(-4, 1));
295 output.writeFormula(aTemplate.getTemplate());
297 output.nextRow();
299 // Within Groups
301 // Label
302 output.resetColumn();
303 output.writeString(SC_STRLOAD(RID_STATISTICS_DLGS, STR_ANOVA_LABEL_WITHIN_GROUPS));
304 output.nextColumn();
306 // Sum of Squares
307 OUString aSSPart = lclCreateMultiParameterFormula(aRangeList, OUString("DEVSQ(%RANGE%)"), strWildcardRange, mDocument, mAddressDetails);
308 aTemplate.setTemplate("=SUM(%RANGE%)");
309 aTemplate.applyString(strWildcardRange, aSSPart);
310 aTemplate.autoReplaceAddress("%WITHIN_SS%", output.current());
311 output.writeFormula(aTemplate.getTemplate());
312 output.nextColumn();
314 // Degree of freedom
315 aTemplate.setTemplate("=SUM(%COUNT_RANGE%)-COUNT(%COUNT_RANGE%)");
316 aTemplate.autoReplaceAddress("%WITHIN_DF%", output.current());
317 output.writeFormula(aTemplate.getTemplate());
318 output.nextColumn();
320 // MS
321 aTemplate.setTemplate("=%WITHIN_SS% / %WITHIN_DF%");
322 output.writeFormula(aTemplate.getTemplate());
324 output.nextRow();
326 // Total
328 // Label
329 output.resetColumn();
330 output.writeString(SC_STRLOAD(RID_STATISTICS_DLGS, STR_ANOVA_LABEL_TOTAL));
331 output.nextColumn();
333 // Sum of Squares
334 aTemplate.setTemplate("=DEVSQ(%RANGE_LIST%)");
335 aTemplate.applyRangeList("%RANGE_LIST%", aRangeList);
336 output.writeFormula(aTemplate.getTemplate());
337 output.nextColumn();
339 // Degree of freedom
340 aTemplate.setTemplate("=SUM(%COUNT_RANGE%) - 1");
341 output.writeFormula(aTemplate.getTemplate());
343 output.nextRow();
346 void ScAnalysisOfVarianceDialog::AnovaTwoFactor(AddressWalkerWriter& output, FormulaTemplate& aTemplate)
348 output.writeBoldString(SC_STRLOAD(RID_STATISTICS_DLGS, STR_ANOVA_TWO_FACTOR_LABEL));
349 output.newLine();
351 double aAlphaValue = mpAlphaField->GetValue() / 100.0;
352 output.writeString("Alpha");
353 output.nextColumn();
354 output.writeValue(aAlphaValue);
355 aTemplate.autoReplaceAddress("%ALPHA%", output.current());
356 output.newLine();
357 output.newLine();
359 // Write labels
360 for(sal_Int32 i = 0; lclBasicStatistics[i].aLabelId != 0; i++)
362 output.writeString(SC_STRLOAD(RID_STATISTICS_DLGS, lclBasicStatistics[i].aLabelId));
363 output.nextColumn();
365 output.newLine();
367 ScRangeList aColumnRangeList;
368 ScRangeList aRowRangeList;
370 lclMakeSubRangesList(aColumnRangeList, mInputRange, BY_COLUMN);
371 lclMakeSubRangesList(aRowRangeList, mInputRange, BY_ROW);
373 // Write ColumnX values
374 output.push();
375 for(sal_Int32 i = 0; lclBasicStatistics[i].aLabelId != 0; i++)
377 output.resetRow();
378 ScRange aResultRange;
379 OUString sFormula = OUString::createFromAscii(lclBasicStatistics[i].aFormula);
380 RowColumn(aColumnRangeList, output, aTemplate, sFormula, BY_COLUMN, &aResultRange);
381 if (lclBasicStatistics[i].aResultRangeName != NULL)
383 OUString sResultRangeName = OUString::createFromAscii(lclBasicStatistics[i].aResultRangeName);
384 aTemplate.autoReplaceRange("%" + sResultRangeName + "_COLUMN%", aResultRange);
386 output.nextColumn();
388 output.newLine();
390 // Write RowX values
391 output.push();
392 for(sal_Int32 i = 0; lclBasicStatistics[i].aLabelId != 0; i++)
394 output.resetRow();
395 ScRange aResultRange;
396 OUString sFormula = OUString::createFromAscii(lclBasicStatistics[i].aFormula);
397 RowColumn(aRowRangeList, output, aTemplate, sFormula, BY_ROW, &aResultRange);
399 if (lclBasicStatistics[i].aResultRangeName != NULL)
401 OUString sResultRangeName = OUString::createFromAscii(lclBasicStatistics[i].aResultRangeName);
402 aTemplate.autoReplaceRange("%" + sResultRangeName + "_ROW%", aResultRange);
404 output.nextColumn();
406 output.newLine();
408 // Write ANOVA labels
409 for(sal_Int32 i = 0; lclAnovaLabels[i] != 0; i++)
411 output.writeString(SC_STRLOAD(RID_STATISTICS_DLGS, lclAnovaLabels[i]));
412 output.nextColumn();
414 output.nextRow();
416 // Setup auto-replace strings
417 aTemplate.autoReplaceRange(strWildcardRange, mInputRange);
418 aTemplate.autoReplaceRange("%FIRST_COLUMN%", *aColumnRangeList[0]);
419 aTemplate.autoReplaceRange("%FIRST_ROW%", *aRowRangeList[0]);
421 // Rows
423 // Label
424 output.resetColumn();
425 output.writeString("Rows");
426 output.nextColumn();
428 // Sum of Squares
429 aTemplate.setTemplate("=SUMPRODUCT(%SUM_RANGE_ROW%;%MEAN_RANGE_ROW%) - SUM(%RANGE%)^2 / COUNT(%RANGE%)");
430 aTemplate.autoReplaceAddress("%ROW_SS%", output.current());
431 output.writeFormula(aTemplate.getTemplate());
432 output.nextColumn();
434 // Degree of freedom
435 aTemplate.setTemplate("=MAX(%COUNT_RANGE_COLUMN%) - 1");
436 aTemplate.autoReplaceAddress("%ROW_DF%", output.current());
437 output.writeFormula(aTemplate.getTemplate());
438 output.nextColumn();
440 // MS
441 aTemplate.setTemplate("=%ROW_SS% / %ROW_DF%");
442 aTemplate.autoReplaceAddress("%MS_ROW%", output.current());
443 output.writeFormula(aTemplate.getTemplate());
444 output.nextColumn();
446 // F
447 aTemplate.setTemplate("=%MS_ROW% / %MS_ERROR%");
448 aTemplate.applyAddress("%MS_ERROR%", output.current(-1, 2));
449 aTemplate.autoReplaceAddress("%F_ROW%", output.current());
450 output.writeFormula(aTemplate.getTemplate());
451 output.nextColumn();
453 // P-value
454 aTemplate.setTemplate("=FDIST(%F_ROW%; %ROW_DF%; %ERROR_DF%");
455 aTemplate.applyAddress("%ERROR_DF%", output.current(-3, 2));
456 output.writeFormula(aTemplate.getTemplate());
457 output.nextColumn();
459 // F critical
460 aTemplate.setTemplate("=FINV(%ALPHA%; %ROW_DF%; %ERROR_DF%");
461 aTemplate.applyAddress("%ERROR_DF%", output.current(-4, 2));
462 output.writeFormula(aTemplate.getTemplate());
463 output.nextColumn();
465 output.nextRow();
467 // Columns
469 // Label
470 output.resetColumn();
471 output.writeString("Columns");
472 output.nextColumn();
474 // Sum of Squares
475 aTemplate.setTemplate("=SUMPRODUCT(%SUM_RANGE_COLUMN%;%MEAN_RANGE_COLUMN%) - SUM(%RANGE%)^2 / COUNT(%RANGE%)");
476 aTemplate.autoReplaceAddress("%COLUMN_SS%", output.current());
477 output.writeFormula(aTemplate.getTemplate());
478 output.nextColumn();
480 // Degree of freedom
481 aTemplate.setTemplate("=MAX(%COUNT_RANGE_ROW%) - 1");
482 aTemplate.autoReplaceAddress("%COLUMN_DF%", output.current());
483 output.writeFormula(aTemplate.getTemplate());
484 output.nextColumn();
486 // MS
487 aTemplate.setTemplate("=%COLUMN_SS% / %COLUMN_DF%");
488 aTemplate.autoReplaceAddress("%MS_COLUMN%", output.current());
489 output.writeFormula(aTemplate.getTemplate());
490 output.nextColumn();
492 // F
493 aTemplate.setTemplate("=%MS_COLUMN% / %MS_ERROR%");
494 aTemplate.applyAddress("%MS_ERROR%", output.current(-1, 1));
495 aTemplate.autoReplaceAddress("%F_COLUMN%", output.current());
496 output.writeFormula(aTemplate.getTemplate());
497 output.nextColumn();
499 // P-value
500 aTemplate.setTemplate("=FDIST(%F_COLUMN%; %COLUMN_DF%; %ERROR_DF%");
501 aTemplate.applyAddress("%ERROR_DF%", output.current(-3, 1));
502 output.writeFormula(aTemplate.getTemplate());
503 output.nextColumn();
505 // F critical
506 aTemplate.setTemplate("=FINV(%ALPHA%; %COLUMN_DF%; %ERROR_DF%");
507 aTemplate.applyAddress("%ERROR_DF%", output.current(-4, 1));
508 output.writeFormula(aTemplate.getTemplate());
509 output.nextColumn();
511 output.nextRow();
513 // Error
515 // Label
516 output.resetColumn();
517 output.writeString("Error");
518 output.nextColumn();
520 // Sum of Squares
521 aTemplate.setTemplate("=SUMSQ(%RANGE%)+SUM(%RANGE%)^2/COUNT(%RANGE%) - (SUMPRODUCT(%SUM_RANGE_ROW%;%MEAN_RANGE_ROW%) + SUMPRODUCT(%SUM_RANGE_COLUMN%;%MEAN_RANGE_COLUMN%))");
522 aTemplate.autoReplaceAddress("%ERROR_SS%", output.current());
523 output.writeFormula(aTemplate.getTemplate());
524 output.nextColumn();
526 // Degree of freedom
527 aTemplate.setTemplate("=%TOTAL_DF% - %ROW_DF% - %COLUMN_DF%");
528 aTemplate.applyAddress("%TOTAL_DF%", output.current(0,1,0));
529 aTemplate.autoReplaceAddress("%ERROR_DF%", output.current());
530 output.writeFormula(aTemplate.getTemplate());
531 output.nextColumn();
533 // MS
534 aTemplate.setTemplate("=%ERROR_SS% / %ERROR_DF%");
535 output.writeFormula(aTemplate.getTemplate());
537 output.nextRow();
539 // Total
541 // Label
542 output.resetColumn();
543 output.writeString("Total");
544 output.nextColumn();
546 // Sum of Squares
547 aTemplate.setTemplate("=SUM(%ROW_SS%;%COLUMN_SS%;%ERROR_SS%)");
548 output.writeFormula(aTemplate.getTemplate());
549 output.nextColumn();
551 // Degree of freedom
552 aTemplate.setTemplate("=COUNT(%RANGE%)-1");
553 output.writeFormula(aTemplate.getTemplate());
554 output.nextColumn();
558 ScRange ScAnalysisOfVarianceDialog::ApplyOutput(ScDocShell* pDocShell)
560 AddressWalkerWriter output(mOutputAddress, pDocShell, mDocument,
561 formula::FormulaGrammar::mergeToGrammar(formula::FormulaGrammar::GRAM_ENGLISH, mAddressDetails.eConv));
562 FormulaTemplate aTemplate(mDocument);
564 if (meFactor == SINGLE_FACTOR)
566 AnovaSingleFactor(output, aTemplate);
568 else if (meFactor == TWO_FACTOR)
570 AnovaTwoFactor(output, aTemplate);
573 return ScRange(output.mMinimumAddress, output.mMaximumAddress);
576 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */