Files
libreoffice/sc/source/ui/StatisticsDialogs/AnalysisOfVarianceDialog.cxx

319 lines
13 KiB
C++
Raw Normal View History

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
*/
#include <sfx2/dispatch.hxx>
#include <svl/zforlist.hxx>
#include <svl/undo.hxx>
#include "formulacell.hxx"
#include "rangelst.hxx"
#include "scitems.hxx"
#include "docsh.hxx"
#include "document.hxx"
#include "uiitems.hxx"
#include "reffact.hxx"
#include "scresid.hxx"
#include "random.hxx"
#include "docfunc.hxx"
#include "globstr.hrc"
#include "sc.hrc"
#include "AnalysisOfVarianceDialog.hxx"
namespace
{
static const char* lclBasicStatisticsLabels[] =
{
"Groups", "Count", "Sum", "Mean", "Variance", NULL
};
static const char* lclAnovaLabels[] =
{
"Source of Variation", "SS", "df", "MS", "F", "P-value", "F critical", NULL
};
static const char* lclAnovaFormula[] =
{
"=COUNT(%RANGE%)", "=SUM(%RANGE%)", "=AVERAGE(%RANGE%)", "=VAR(%RANGE%)", NULL
};
static const OUString lclWildcardRange("%RANGE%");
OUString lclCreateMultiParameterFormula(
ScRangeList& aRangeList, const OUString& aFormulaTemplate,
const OUString& aWildcard, ScDocument* pDocument,
ScAddress::Details& aAddressDetails)
{
OUString aResult;
for (size_t i = 0; i < aRangeList.size(); i++)
{
OUString aRangeString;
aRangeList[i]->Format( aRangeString, SCR_ABS, pDocument, aAddressDetails );
OUString aFormulaString = aFormulaTemplate.replaceAll(aWildcard, aRangeString);
aResult += aFormulaString;
if(i != aRangeList.size() - 1) // Not Last
aResult+= ";";
}
return aResult;
}
class CellAddressIterator
{
public:
CellAddressIterator(ScAddress& aStartAddress)
{}
virtual ~CellAddressIterator()
{}
};
}
ScAnalysisOfVarianceDialog::ScAnalysisOfVarianceDialog(
SfxBindings* pSfxBindings, SfxChildWindow* pChildWindow,
Window* pParent, ScViewData* pViewData ) :
ScStatisticsInputOutputDialog(
pSfxBindings, pChildWindow, pParent, pViewData,
"AnalysisOfVarianceDialog", "modules/scalc/ui/analysisofvariancedialog.ui" )
{
get(mpAlpha, "alpha-spin");
}
ScAnalysisOfVarianceDialog::~ScAnalysisOfVarianceDialog()
{}
sal_Bool ScAnalysisOfVarianceDialog::Close()
{
return DoClose( ScAnalysisOfVarianceDialogWrapper::GetChildWindowId() );
}
void ScAnalysisOfVarianceDialog::CalculateInputAndWriteToOutput( )
{
OUString aUndo("Analysis Of Variance");
ScDocShell* pDocShell = mViewData->GetDocShell();
svl::IUndoManager* pUndoManager = pDocShell->GetUndoManager();
pUndoManager->EnterListAction( aUndo, aUndo );
ScAddress aStart = mInputRange.aStart;
ScAddress aEnd = mInputRange.aEnd;
SCTAB outTab = mOutputAddress.Tab();
SCCOL outCol = mOutputAddress.Col();
SCROW outRow = mOutputAddress.Row();
OUString aReferenceString;
ScAddress aAddress;
for (SCROW inTab = aStart.Tab(); inTab <= aEnd.Tab(); inTab++)
{
outCol = mOutputAddress.Col();
// Write labels
for(sal_Int32 i = 0; lclBasicStatisticsLabels[i] != NULL; i++)
{
aAddress = ScAddress(outCol, outRow, outTab);
OUString aCalculationName(OUString::createFromAscii(lclBasicStatisticsLabels[i]));
pDocShell->GetDocFunc().SetStringCell(aAddress, aCalculationName, true);
outCol++;
}
outRow++;
ScRangeList aRangeList;
// Write statistic formulas for columns
for (SCCOL inCol = aStart.Col(); inCol <= aEnd.Col(); inCol++)
{
outCol = mOutputAddress.Col();
aAddress = ScAddress(outCol, outRow, outTab);
OUString aGroupName = OUString("Column ") + OUString::number(inCol - aStart.Col() + 1);
pDocShell->GetDocFunc().SetStringCell(aAddress, aGroupName, true);
outCol++;
ScRange aColumnRange (
ScAddress(inCol, aStart.Row(), inTab),
ScAddress(inCol, aEnd.Row(), inTab)
);
aRangeList.Append(aColumnRange);
aColumnRange.Format( aReferenceString, SCR_ABS, mDocument, mAddressDetails );
OUString aFormulaString;
OUString aFormulaTemplate;
for(sal_Int32 i = 0; lclAnovaFormula[i] != NULL; i++)
{
aAddress = ScAddress(outCol, outRow, outTab);
aFormulaTemplate = OUString::createFromAscii(lclAnovaFormula[i]);
aFormulaString = aFormulaTemplate.replaceAll(lclWildcardRange, aReferenceString);
pDocShell->GetDocFunc().SetFormulaCell(aAddress, new ScFormulaCell(mDocument, aAddress, aFormulaString), true);
outCol++;
}
outRow++;
}
outRow++; // Blank row
// Write ANOVA labels
outCol = mOutputAddress.Col();
for(sal_Int32 i = 0; lclAnovaLabels[i] != NULL; i++)
{
aAddress = ScAddress(outCol, outRow, outTab);
OUString aCalculationName(OUString::createFromAscii(lclAnovaLabels[i]));
pDocShell->GetDocFunc().SetStringCell(aAddress, aCalculationName, true);
outCol++;
}
outRow++;
// Between Groups
{
// Label
outCol = mOutputAddress.Col();
aAddress = ScAddress(outCol, outRow, outTab);
pDocShell->GetDocFunc().SetStringCell(aAddress, OUString("Between Groups"), true);
outCol++;
// Sum of Squares
aAddress = ScAddress(outCol, outRow, outTab);
OUString aReferenceTotal;
OUString aReferenceWithin;
ScAddress aAddressTotal(outCol, outRow+2, outTab);
aAddressTotal.Format( aReferenceTotal, SCR_ABS, mDocument, mAddressDetails );
ScAddress aAddressWithin(outCol, outRow+1, outTab);
aAddressWithin.Format( aReferenceWithin, SCR_ABS, mDocument, mAddressDetails );
OUString aFormulaString = "=" + aReferenceTotal + "-" + aReferenceWithin;
pDocShell->GetDocFunc().SetFormulaCell(aAddress, new ScFormulaCell(mDocument, aAddress, aFormulaString), true);
outCol++;
// Degree of freedom
aAddress = ScAddress(outCol, outRow, outTab);
aAddressTotal = ScAddress(outCol, outRow+2, outTab);
aAddressTotal.Format( aReferenceTotal, SCR_ABS, mDocument, mAddressDetails );
aAddressWithin = ScAddress(outCol, outRow+1, outTab);
aAddressWithin.Format( aReferenceWithin, SCR_ABS, mDocument, mAddressDetails );
aFormulaString = "=" + aReferenceTotal + "-" + aReferenceWithin;
pDocShell->GetDocFunc().SetFormulaCell(aAddress, new ScFormulaCell(mDocument, aAddress, aFormulaString), true);
outCol++;
// MS
OUString aSSRef;
ScAddress(outCol-2, outRow, outTab).Format( aSSRef, SCR_ABS, mDocument, mAddressDetails );
OUString aDFRef;
ScAddress(outCol-1, outRow, outTab).Format( aDFRef, SCR_ABS, mDocument, mAddressDetails );
aFormulaString = "=" + aSSRef + "/" + aDFRef;
aAddress = ScAddress(outCol, outRow, outTab);
pDocShell->GetDocFunc().SetFormulaCell(aAddress, new ScFormulaCell(mDocument, aAddress, aFormulaString), true);
outCol++;
// F
aAddress = ScAddress(outCol, outRow, outTab);
OUString aMSBetween;
ScAddress(outCol-1, outRow, outTab).Format( aMSBetween, SCR_ABS, mDocument, mAddressDetails );
OUString aMSWithin;
ScAddress(outCol-1, outRow+1, outTab).Format( aMSWithin, SCR_ABS, mDocument, mAddressDetails );
aFormulaString = "=" + aMSBetween + "/" + aMSWithin;
pDocShell->GetDocFunc().SetFormulaCell(aAddress, new ScFormulaCell(mDocument, aAddress, aFormulaString), true);
outCol++;
// P-value
aAddress = ScAddress(outCol, outRow, outTab);
OUString aFValue;
ScAddress(outCol-1, outRow, outTab).Format( aFValue, SCR_ABS, mDocument, mAddressDetails );
OUString aDFBetween;
ScAddress(outCol-3, outRow, outTab).Format( aDFBetween, SCR_ABS, mDocument, mAddressDetails );
OUString aDFWithin;
ScAddress(outCol-3, outRow+1, outTab).Format( aDFWithin, SCR_ABS, mDocument, mAddressDetails );
aFormulaString = "=FDIST("+ aFValue + ";" + aDFBetween + ";" + aDFWithin + ")";
pDocShell->GetDocFunc().SetFormulaCell(aAddress, new ScFormulaCell(mDocument, aAddress, aFormulaString), true);
outCol++;
// F critical
double aAlphaValue = mpAlpha->GetValue() / 100.0;
OUString aAlphaString = rtl::math::doubleToUString(
aAlphaValue, rtl_math_StringFormat_Automatic, rtl_math_DecimalPlaces_Max,
ScGlobal::pLocaleData->getNumDecimalSep()[0], true);
aAddress = ScAddress(outCol, outRow, outTab);
aFormulaString = "=FINV(" + aAlphaString + ";" + aDFBetween + ";" + aDFWithin + ")";
pDocShell->GetDocFunc().SetFormulaCell(aAddress, new ScFormulaCell(mDocument, aAddress, aFormulaString), true);
}
outRow++;
// Within Groups
{
// Label
outCol = mOutputAddress.Col();
aAddress = ScAddress(outCol, outRow, outTab);
pDocShell->GetDocFunc().SetStringCell(aAddress, OUString("Within Groups"), true);
outCol++;
// Sum of Squares
aAddress = ScAddress(outCol, outRow, outTab);
OUString aSum("=SUM(%RANGE%)");
OUString aDevSQ("DEVSQ(%RANGE%)");
OUString aSSPart = lclCreateMultiParameterFormula(aRangeList, aDevSQ, lclWildcardRange, mDocument, mAddressDetails);
OUString aSS = aSum.replaceAll(lclWildcardRange, aSSPart);
pDocShell->GetDocFunc().SetFormulaCell(aAddress, new ScFormulaCell(mDocument, aAddress, aSS), true);
outCol++;
// Degree of freedom
aAddress = ScAddress(outCol, outRow, outTab);
OUString aCountMinusOne("COUNT(%RANGE%)-1");
OUString aDFPart = lclCreateMultiParameterFormula(aRangeList, aCountMinusOne, lclWildcardRange, mDocument, mAddressDetails);
OUString aDF = aSum.replaceAll(lclWildcardRange, aDFPart);
pDocShell->GetDocFunc().SetFormulaCell(aAddress, new ScFormulaCell(mDocument, aAddress, aDF), true);
outCol++;
// MS
OUString aSSRef;
OUString aDFRef;
ScAddress aAddressSS(outCol-2, outRow, outTab);
aAddressSS.Format( aSSRef, SCR_ABS, mDocument, mAddressDetails );
ScAddress aAddressDF(outCol-1, outRow, outTab);
aAddressDF.Format( aDFRef, SCR_ABS, mDocument, mAddressDetails );
OUString aFormulaString = "=" + aSSRef + "/" + aDFRef;
aAddress = ScAddress(outCol, outRow, outTab);
pDocShell->GetDocFunc().SetFormulaCell(aAddress, new ScFormulaCell(mDocument, aAddress, aFormulaString), true);
}
outRow++;
// Total
{
// Label
outCol = mOutputAddress.Col();
aAddress = ScAddress(outCol, outRow, outTab);
pDocShell->GetDocFunc().SetStringCell(aAddress, OUString("Total"), true);
outCol++;
// Sum of Squares
OUString aDevSQ("DEVSQ(%RANGE%)");
aRangeList.Format( aReferenceString, SCR_ABS, mDocument );
OUString aFormulaString = aDevSQ.replaceAll(lclWildcardRange, aReferenceString);
aAddress = ScAddress(outCol, outRow, outTab);
pDocShell->GetDocFunc().SetFormulaCell(aAddress, new ScFormulaCell(mDocument, aAddress, "=" + aFormulaString), true);
outCol++;
// Degree of freedom
aAddress = ScAddress(outCol, outRow, outTab);
OUString aCount("COUNT(%RANGE%)");
OUString aSumMinusOne("=SUM(%RANGE%)-1");
OUString aDFPart = lclCreateMultiParameterFormula(aRangeList, aCount, lclWildcardRange, mDocument, mAddressDetails);
OUString aDF = aSumMinusOne.replaceAll(lclWildcardRange, aDFPart);
pDocShell->GetDocFunc().SetFormulaCell(aAddress, new ScFormulaCell(mDocument, aAddress, aDF), true);
}
outRow++;
}
ScRange aOutputRange(mOutputAddress, ScAddress(outTab, outRow, outTab) );
pUndoManager->LeaveListAction();
pDocShell->PostPaint( aOutputRange, PAINT_GRID );
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */