Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/LibreOffice/sc/source/ui/dbgui/   (Office von Apache Version 25.8.3.2©)  Datei vom 5.10.2025 mit Größe 18 kB image not shown  

Quelle  consdlg.cxx   Sprache: C

 
/* -*- 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/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */


#include <sfx2/dispatch.hxx>

#include <tabvwsh.hxx>
#include <uiitems.hxx>
#include <dbdata.hxx>
#include <rangenam.hxx>
#include <rangeutl.hxx>
#include <reffact.hxx>
#include <document.hxx>
#include <scresid.hxx>

#include <globstr.hrc>
#include <strings.hrc>

#include <consdlg.hxx>
#include <o3tl/safeint.hxx>
#include <vcl/svapp.hxx>
#include <vcl/weld.hxx>

namespace
{
    void INFOBOX(weld::Window* pWindow, TranslateId id)
    {
        std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(pWindow,
                                                      VclMessageType::Info, VclButtonsType::Ok,
                                                      ScResId(id)));
        xInfoBox->run();
    }
}

class ScAreaData
{
public:
    ScAreaData()
    {
    }

    void Set( const OUString& rName, const OUString& rArea )
    {
        aStrName  = rName;
        aStrArea  = rArea;
    }

    OUString  aStrName;
    OUString  aStrArea;
};

ScConsolidateDlg::ScConsolidateDlg(SfxBindings* pB, SfxChildWindow* pCW, weld::Window* pParent,
                                   const SfxItemSet& rArgSet)

    : ScAnyRefDlgController(pB, pCW, pParent, u"modules/scalc/ui/consolidatedialog.ui"_ustr, u"ConsolidateDialog"_ustr)
    , aStrUndefined   ( ScResId( SCSTR_UNDEFINED ) )
    , theConsData     ( static_cast<const ScConsolidateItem&>(
                         rArgSet.Get( rArgSet.GetPool()->
                                          GetWhichIDFromSlotID( SID_CONSOLIDATE ) )
                                    ).GetData() )
    , rViewData       ( static_cast<ScTabViewShell*>(SfxViewShell::Current())->
                              GetViewData() )
    , rDoc            ( static_cast<ScTabViewShell*>(SfxViewShell::Current())->
                              GetViewData().GetDocument() )
    , nAreaDataCount  ( 0 )
    , nWhichCons      ( rArgSet.GetPool()->GetWhichIDFromSlotID( SID_CONSOLIDATE ) )
    , bDlgLostFocus   ( false )
    , m_xLbFunc(m_xBuilder->weld_combo_box(u"func"_ustr))
    , m_xLbConsAreas(m_xBuilder->weld_tree_view(u"consareas"_ustr))
    , m_xLbDataArea(m_xBuilder->weld_combo_box(u"lbdataarea"_ustr))
    , m_xEdDataArea(new formula::RefEdit(m_xBuilder->weld_entry(u"eddataarea"_ustr)))
    , m_xRbDataArea(new formula::RefButton(m_xBuilder->weld_button(u"rbdataarea"_ustr)))
    , m_xLbDestArea(m_xBuilder->weld_combo_box(u"lbdestarea"_ustr))
    , m_xEdDestArea(new formula::RefEdit(m_xBuilder->weld_entry(u"eddestarea"_ustr)))
    , m_xRbDestArea(new formula::RefButton(m_xBuilder->weld_button(u"rbdestarea"_ustr)))
    , m_xExpander(m_xBuilder->weld_expander(u"more"_ustr))
    , m_xBtnByRow(m_xBuilder->weld_check_button(u"byrow"_ustr))
    , m_xBtnByCol(m_xBuilder->weld_check_button(u"bycol"_ustr))
    , m_xBtnRefs(m_xBuilder->weld_check_button(u"refs"_ustr))
    , m_xBtnOk(m_xBuilder->weld_button(u"ok"_ustr))
    , m_xBtnCancel(m_xBuilder->weld_button(u"cancel"_ustr))
    , m_xBtnAdd(m_xBuilder->weld_button(u"add"_ustr))
    , m_xBtnRemove(m_xBuilder->weld_button(u"delete"_ustr))
    , m_xDataFT(m_xBuilder->weld_label(u"ftdataarea"_ustr))
    , m_xDestFT(m_xBuilder->weld_label(u"ftdestarea"_ustr))
{
    m_pRefInputEdit = m_xEdDataArea.get();
    Init();
}

ScConsolidateDlg::~ScConsolidateDlg()
{
}

void ScConsolidateDlg::Init()
{
    OUString aStr;
    sal_uInt16 i=0;

    m_xRbDataArea->SetReferences(this, m_xEdDataArea.get());
    m_xEdDataArea->SetReferences(this, m_xDataFT.get());
    m_xRbDestArea->SetReferences(this, m_xEdDestArea.get());
    m_xEdDestArea->SetReferences(this, m_xDestFT.get());

    m_xEdDataArea->SetGetFocusHdl( LINK( this, ScConsolidateDlg, GetEditFocusHdl ) );
    m_xEdDestArea->SetGetFocusHdl( LINK( this, ScConsolidateDlg, GetEditFocusHdl ) );
    m_xLbDataArea->connect_focus_in( LINK( this, ScConsolidateDlg, GetFocusHdl ) );
    m_xLbDestArea->connect_focus_in( LINK( this, ScConsolidateDlg, GetFocusHdl ) );
    m_xEdDataArea->SetModifyHdl( LINK( this, ScConsolidateDlg, ModifyHdl ) );
    m_xEdDestArea->SetModifyHdl( LINK( this, ScConsolidateDlg, ModifyHdl ) );
    m_xLbConsAreas->connect_selection_changed(LINK(this, ScConsolidateDlg, SelectTVHdl));
    m_xLbDataArea->connect_changed( LINK( this, ScConsolidateDlg, SelectCBHdl ) );
    m_xLbDestArea->connect_changed( LINK( this, ScConsolidateDlg, SelectCBHdl ) );
    m_xBtnOk->connect_clicked( LINK( this, ScConsolidateDlg, OkHdl ) );
    m_xBtnCancel->connect_clicked( LINK( this, ScConsolidateDlg, ClickHdl ) );
    m_xBtnAdd->connect_clicked( LINK( this, ScConsolidateDlg, ClickHdl ) );
    m_xBtnRemove->connect_clicked( LINK( this, ScConsolidateDlg, ClickHdl ) );

    m_xBtnAdd->set_sensitive(false);
    m_xBtnRemove->set_sensitive(false);

    m_xBtnByRow->set_active( theConsData.bByRow );
    m_xBtnByCol->set_active( theConsData.bByCol );
    m_xBtnRefs->set_active( theConsData.bReferenceData );

    m_xLbFunc->set_active( FuncToLbPos( theConsData.eFunction ) );

    m_xLbConsAreas->set_selection_mode(SelectionMode::Multiple);
    m_xLbConsAreas->set_size_request(m_xLbConsAreas->get_approximate_digit_width() * 16,
                                     m_xLbConsAreas->get_height_rows(5));

    // read consolidation areas
    m_xLbConsAreas->clear();
    const formula::FormulaGrammar::AddressConvention eConv = rDoc.GetAddressConvention();
    for ( i=0; i<theConsData.nDataAreaCount; i++ )
    {
        const ScArea& rArea = theConsData.pDataAreas[i];
        if ( rArea.nTab < rDoc.GetTableCount() )
        {
            aStr = ScRange( rArea.nColStart, rArea.nRowStart, rArea.nTab,
                    rArea.nColEnd, rArea.nRowEnd, rArea.nTab ).Format( rDoc,
                        ScRefFlags::RANGE_ABS_3D, eConv );
            m_xLbConsAreas->append_text(aStr);
        }
    }

    if ( theConsData.nTab < rDoc.GetTableCount() )
    {
        aStr = ScAddress( theConsData.nCol, theConsData.nRow, theConsData.nTab
                ).Format( ScRefFlags::ADDR_ABS_3D, &rDoc, eConv );
        m_xEdDestArea->SetText( aStr );
    }
    else
        m_xEdDestArea->SetText(OUString());

    // Use the ScAreaData helper class to save those range names from the
    // RangeNames and database ranges that appear in the ListBoxes.

    ScRangeName*    pRangeNames  = rDoc.GetRangeName();
    ScDBCollection* pDbNames     = rDoc.GetDBCollection();
    size_t nRangeCount = pRangeNames ? pRangeNames->size() : 0;
    size_t nDbCount = pDbNames ? pDbNames->getNamedDBs().size() : 0;

    nAreaDataCount = nRangeCount+nDbCount;
    pAreaData      = nullptr;

    if ( nAreaDataCount > 0 )
    {
        pAreaData.reset( new ScAreaData[nAreaDataCount] );

        OUString aStrName;
        sal_uInt16 nAt = 0;
        ScRange aRange;
        ScAreaNameIterator aIter( rDoc );
        while ( aIter.Next( aStrName, aRange ) )
        {
            OUString aStrArea(aRange.Format(rDoc, ScRefFlags::ADDR_ABS_3D, eConv));
            pAreaData[nAt++].Set( aStrName, aStrArea );
        }
    }

    FillAreaLists();
    ModifyHdl( *m_xEdDestArea );
    m_xLbDataArea->set_active( 0 );
    m_xEdDataArea->SetText(OUString());
    m_xEdDataArea->GrabFocus();

    //aFlSep.SetStyle( aFlSep.GetStyle() | WB_VERT );

    //@BugID 54702 enable/disable only in base class
    //SFX_APPWINDOW->set_sensitive(true);
}

void ScConsolidateDlg::FillAreaLists()
{
    m_xLbDataArea->clear();
    m_xLbDestArea->clear();
    m_xLbDataArea->append_text( aStrUndefined );
    m_xLbDestArea->append_text( aStrUndefined );

    if ( pAreaData && (nAreaDataCount > 0) )
    {
        for ( size_t i=0;
              (i<nAreaDataCount) && (!pAreaData[i].aStrName.isEmpty());
              i++ )
        {
            m_xLbDataArea->append_text(pAreaData[i].aStrName);
            m_xLbDestArea->append_text(pAreaData[i].aStrName);
        }
    }
}

// Handover of a range within a table that has been selected by the mouse.
// This range is then shown in the reference window as new selection.

void ScConsolidateDlg::SetReference( const ScRange& rRef, ScDocument& rDocP )
{
    if ( !m_pRefInputEdit )
        return;

    if ( rRef.aStart != rRef.aEnd )
        RefInputStart( m_pRefInputEdit );

    OUString      aStr;
    ScRefFlags      nFmt = ScRefFlags::RANGE_ABS_3D;       //!!! nCurTab is still missing
    const formula::FormulaGrammar::AddressConvention eConv = rDocP.GetAddressConvention();

    if ( rRef.aStart.Tab() != rRef.aEnd.Tab() )
        nFmt |= ScRefFlags::TAB2_3D;

    if ( m_pRefInputEdit == m_xEdDataArea.get())
        aStr = rRef.Format(rDocP, nFmt, eConv);
    else if ( m_pRefInputEdit == m_xEdDestArea.get() )
        aStr = rRef.aStart.Format(nFmt, &rDocP, eConv);

    m_pRefInputEdit->SetRefString( aStr );
    ModifyHdl( *m_pRefInputEdit );
}

void ScConsolidateDlg::Close()
{
    DoClose( ScConsolidateDlgWrapper::GetChildWindowId() );
}

void ScConsolidateDlg::SetActive()
{
    if ( bDlgLostFocus )
    {
        bDlgLostFocus = false;

        if ( m_pRefInputEdit )
        {
            m_pRefInputEdit->GrabFocus();
            ModifyHdl( *m_pRefInputEdit );
        }
    }
    else
        m_xDialog->grab_focus();

    RefInputDone();
}

void ScConsolidateDlg::Deactivate()
{
    bDlgLostFocus = true;
}

bool ScConsolidateDlg::VerifyEdit( formula::RefEdit* pEd )
{
    if (pEd != m_xEdDataArea.get() && pEd != m_xEdDestArea.get())
        return false;

    SCTAB    nTab    = rViewData.GetTabNo();
    bool bEditOk = false;
    OUString theCompleteStr;
    const formula::FormulaGrammar::AddressConvention eConv = rDoc.GetAddressConvention();

    if ( pEd == m_xEdDataArea.get() )
    {
        bEditOk = ScRangeUtil::IsAbsArea( pEd->GetText(), rDoc,
                                         nTab, &theCompleteStr, nullptr, nullptr, eConv );
    }
    else if ( pEd == m_xEdDestArea.get() )
    {
        OUString aPosStr;

        ScRangeUtil::CutPosString( pEd->GetText(), aPosStr );
        bEditOk = ScRangeUtil::IsAbsPos( aPosStr, rDoc,
                                        nTab, &theCompleteStr, nullptr, eConv );
    }

    if ( bEditOk )
        pEd->SetText( theCompleteStr );

    return bEditOk;
}

// Handler:

IMPL_LINK( ScConsolidateDlg, GetEditFocusHdl, formula::RefEdit&, rControl, void )
{
    m_pRefInputEdit = &rControl;
}

IMPL_LINK( ScConsolidateDlg, GetFocusHdl, weld::Widget&, rControl, void )
{
    if (&rControl == m_xLbDataArea.get())
        m_pRefInputEdit = m_xEdDataArea.get();
    else if (&rControl == m_xLbDestArea.get())
        m_pRefInputEdit = m_xEdDestArea.get();
}

IMPL_LINK_NOARG(ScConsolidateDlg, OkHdl, weld::Button&, void)
{
    const sal_Int32 nDataAreaCount = m_xLbConsAreas->n_children();

    if ( nDataAreaCount > 0 )
    {
        ScRefAddress aDestAddress;
        SCTAB       nTab = rViewData.GetTabNo();
        OUString    aDestPosStr( m_xEdDestArea->GetText() );
        const formula::FormulaGrammar::AddressConvention eConv = rDoc.GetAddressConvention();

        if ( ScRangeUtil::IsAbsPos( aDestPosStr, rDoc, nTab, nullptr, &aDestAddress, eConv ) )
        {
            ScConsolidateParam  theOutParam( theConsData );
            std::unique_ptr<ScArea[]> pDataAreas(new ScArea[nDataAreaCount]);

            for ( sal_Int32 i=0; i<nDataAreaCount; ++i )
            {
                ScRangeUtil::MakeArea(m_xLbConsAreas->get_text(i),
                                      pDataAreas[i], rDoc, nTab, eConv);
            }

            theOutParam.nCol            = aDestAddress.Col();
            theOutParam.nRow            = aDestAddress.Row();
            theOutParam.nTab            = aDestAddress.Tab();
            theOutParam.eFunction       = LbPosToFunc( m_xLbFunc->get_active() );
            theOutParam.bByCol          = m_xBtnByCol->get_active();
            theOutParam.bByRow          = m_xBtnByRow->get_active();
            theOutParam.bReferenceData  = m_xBtnRefs->get_active();
            theOutParam.SetAreas( std::move(pDataAreas), nDataAreaCount );

            ScConsolidateItem aOutItem( nWhichCons, &theOutParam );

            SetDispatcherLock( false );
            SwitchToDocument();
            GetBindings().GetDispatcher()->ExecuteList(SID_CONSOLIDATE,
                                      SfxCallMode::SLOT | SfxCallMode::RECORD,
                                      { &aOutItem });
            response(RET_OK);
        }
        else
        {
            INFOBOX(m_xDialog.get(), STR_INVALID_TABREF);
            m_xEdDestArea->GrabFocus();
        }
    }
    else
        response(RET_CANCEL); // no area defined -> Cancel
}

IMPL_LINK( ScConsolidateDlg, ClickHdl, weld::Button&, rBtn, void )
{
    if ( &rBtn == m_xBtnCancel.get() )
        response(RET_CANCEL);
    else if ( &rBtn == m_xBtnAdd.get() )
    {
        if ( !m_xEdDataArea->GetText().isEmpty() )
        {
            OUString    aNewEntry( m_xEdDataArea->GetText() );
            std::unique_ptr<ScArea[]> ppAreas;
            sal_uInt16      nAreaCount = 0;
            const formula::FormulaGrammar::AddressConvention eConv = rDoc.GetAddressConvention();

            if ( ScRangeUtil::IsAbsTabArea( aNewEntry, &rDoc, &ppAreas, &nAreaCount, true, eConv ) )
            {
                // IsAbsTabArea() creates an array of ScArea pointers,
                // which have been created dynamically as well.
                // These objects need to be deleted here.

                for ( sal_uInt16 i=0; i<nAreaCount; i++ )
                {
                    const ScArea& rArea = ppAreas[i];
                    OUString aNewArea = ScRange( rArea.nColStart, rArea.nRowStart, rArea.nTab,
                            rArea.nColEnd, rArea.nRowEnd, rArea.nTab
                            ).Format(rDoc, ScRefFlags::RANGE_ABS_3D, eConv);

                    if (m_xLbConsAreas->find_text(aNewArea) == -1)
                    {
                        m_xLbConsAreas->append_text( aNewArea );
                    }
                }
            }
            else if ( VerifyEdit( m_xEdDataArea.get() ) )
            {
                OUString aNewArea( m_xEdDataArea->GetText() );

                if (m_xLbConsAreas->find_text(aNewArea) == -1)
                    m_xLbConsAreas->append_text(aNewArea);
                else
                    INFOBOX(m_xDialog.get(), STR_AREA_ALREADY_INSERTED);
            }
            else
            {
                INFOBOX(m_xDialog.get(), STR_INVALID_TABREF);
                m_xEdDataArea->GrabFocus();
            }
        }
    }
    else if ( &rBtn == m_xBtnRemove.get() )
    {
        std::vector<int> aSelectedRows(m_xLbConsAreas->get_selected_rows());
        std::sort(aSelectedRows.begin(), aSelectedRows.end());
        for (auto it = aSelectedRows.rbegin(); it != aSelectedRows.rend(); ++it)
            m_xLbConsAreas->remove(*it);
        m_xBtnRemove->set_sensitive(false);
    }
}

IMPL_LINK( ScConsolidateDlg, SelectTVHdl, weld::TreeView&, rLb, void )
{
    if (rLb.get_selected_index() != -1)
        m_xBtnRemove->set_sensitive(true);
    else
        m_xBtnRemove->set_sensitive(false);
}

IMPL_LINK( ScConsolidateDlg, SelectCBHdl, weld::ComboBox&, rLb, void )
{
    formula::RefEdit* pEd = (&rLb == m_xLbDataArea.get()) ? m_xEdDataArea.get() : m_xEdDestArea.get();
    const sal_Int32 nSelPos = rLb.get_active();

    if (   (nSelPos > 0)
        && (nAreaDataCount > 0)
        && (pAreaData != nullptr) )
    {
        if ( o3tl::make_unsigned(nSelPos) <= nAreaDataCount )
        {
            OUString aString( pAreaData[nSelPos-1].aStrArea );

            if ( &rLb == m_xLbDestArea.get() )
                ScRangeUtil::CutPosString( aString, aString );

            pEd->SetText( aString );

            if ( pEd == m_xEdDataArea.get() )
                m_xBtnAdd->set_sensitive(true);
        }
    }
    else
    {
        pEd->SetText( OUString() );
        if ( pEd == m_xEdDataArea.get() )
            m_xBtnAdd->set_sensitive(true);
    }
}

IMPL_LINK( ScConsolidateDlg, ModifyHdl, formula::RefEdit&, rEd, void )
{
    if ( &rEd == m_xEdDataArea.get() )
    {
        OUString aAreaStr( rEd.GetText() );
        if ( !aAreaStr.isEmpty() )
            m_xBtnAdd->set_sensitive(true);
        else
            m_xBtnAdd->set_sensitive(false);
    }
    else if ( &rEd == m_xEdDestArea.get() )
    {
        m_xLbDestArea->set_active(0);
    }
}

// TODO: generalize!
// Resource of the ListBox and these two conversion methods are also in
// tpsubt and everywhere, where StarCalc functions are selectable.

ScSubTotalFunc ScConsolidateDlg::LbPosToFunc( sal_Int32 nPos )
{
    switch ( nPos )
    {
        case  2:    return SUBTOTAL_FUNC_AVE;
        case  6:    return SUBTOTAL_FUNC_CNT;
        case  1:    return SUBTOTAL_FUNC_CNT2;
        case  3:    return SUBTOTAL_FUNC_MAX;
        case  4:    return SUBTOTAL_FUNC_MIN;
        case  5:    return SUBTOTAL_FUNC_PROD;
        case  7:    return SUBTOTAL_FUNC_STD;
        case  8:    return SUBTOTAL_FUNC_STDP;
        case  9:    return SUBTOTAL_FUNC_VAR;
        case 10:    return SUBTOTAL_FUNC_VARP;
        case  0:
        default:
            return SUBTOTAL_FUNC_SUM;
    }
}

sal_Int32 ScConsolidateDlg::FuncToLbPos( ScSubTotalFunc eFunc )
{
    switch ( eFunc )
    {
        case SUBTOTAL_FUNC_AVE:     return 2;
        case SUBTOTAL_FUNC_CNT:     return 6;
        case SUBTOTAL_FUNC_CNT2:    return 1;
        case SUBTOTAL_FUNC_MAX:     return 3;
        case SUBTOTAL_FUNC_MIN:     return 4;
        case SUBTOTAL_FUNC_PROD:    return 5;
        case SUBTOTAL_FUNC_STD:     return 7;
        case SUBTOTAL_FUNC_STDP:    return 8;
        case SUBTOTAL_FUNC_VAR:     return 9;
        case SUBTOTAL_FUNC_VARP:    return 10;
        case SUBTOTAL_FUNC_NONE:
        case SUBTOTAL_FUNC_SUM:
        default:
            return 0;
    }
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Messung V0.5
C=92 H=96 G=93

¤ Dauer der Verarbeitung: 0.5 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.