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 34 kB image not shown  

Quelle  scuiasciiopt.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 .
 */


#undef SC_DLLIMPLEMENTATION

#include <svx/txencbox.hxx>

#include <global.hxx>
#include <scresid.hxx>
#include <impex.hxx>
#include <scuiasciiopt.hxx>
#include <strings.hrc>
#include <strings.hxx>
#include <csvtablebox.hxx>
#include <osl/thread.h>
#include <unotools/transliterationwrapper.hxx>

#include <optutil.hxx>
#include <com/sun/star/uno/Any.hxx>
#include <com/sun/star/uno/Sequence.hxx>
#include <miscuno.hxx>
#include <osl/diagnose.h>
#include <vcl/svapp.hxx>
#include <comphelper/lok.hxx>
#include <comphelper/sequence.hxx>
#include <o3tl/string_view.hxx>

#include <unicode/ucsdet.h>
#include <sfx2/objsh.hxx>
#include <svx/txenctab.hxx>
#include <unotools/filteroptions_settings.hxx>
#include <unotools/viewoptions.hxx>

//! TODO make dynamic
const SCSIZE ASCIIDLG_MAXROWS                = MAXROWCOUNT;

// Maximum number of source lines to concatenate while generating the preview
// for one logical line. This may result in a wrong preview if the actual
// number of embedded line feeds is greater, but a number too high would take
// too much time (loop excessively if unlimited and large data) if none of the
// selected separators are actually used in data but a field at start of line
// is quoted.
constexpr sal_uInt32 kMaxEmbeddedLinefeeds = 500;

using namespace com::sun::star::uno;

namespace {
// The values of this enum are stored in config's "SeparatorType" node
enum SeparatorType
{
    FIXED = 0,
    SEPARATOR = 1,
    DETECT_SEPARATOR = 2,
};

}

// Config items for all three paths are defined in
// officecfg/registry/schema/org/openoffice/Office/Calc.xcs
// If not, options are neither loaded nor saved.
constexpr OUString CSVIO_MergeDelimiters = u"MergeDelimiters"_ustr;
constexpr OUString CSVIO_Separators = u"Separators"_ustr;
constexpr OUString CSVIO_TextSeparators = u"TextSeparators"_ustr;
constexpr OUString CSVIO_RemoveSpace = u"RemoveSpace"_ustr;
constexpr OUString CSVIO_EvaluateFormulas = u"EvaluateFormulas"_ustr;
constexpr OUString CSVIO_SeparatorType = u"SeparatorType"_ustr;
constexpr OUString CSVIO_FromRow = u"FromRow"_ustr;
constexpr OUString CSVIO_Encoding = u"Encoding"_ustr;
constexpr OUString CSVIO_QuotedAsText = u"QuotedFieldAsText"_ustr;
constexpr OUString CSVIO_DetectSpecialNum = u"DetectSpecialNumbers"_ustr;
constexpr OUString CSVIO_DetectScientificNum = u"DetectScientificNumbers"_ustr;
constexpr OUString CSVIO_Language = u"Language"_ustr;
constexpr OUString CSVIO_SkipEmptyCells = u"SkipEmptyCells"_ustr;

static void lcl_FillCombo(weld::ComboBox& rCombo, std::u16string_view rList, sal_Unicode cSelect)
{
    OUString aStr;
    if (!rList.empty())
    {
        sal_Int32 nIdx {0};
        do
        {
            const OUString sEntry {o3tl::getToken(rList, 0, '\t', nIdx)};
            rCombo.append_text(sEntry);
            if (nIdx>0 && static_cast<sal_Unicode>(o3tl::toInt32(o3tl::getToken(rList, 0, '\t', nIdx))) == cSelect)
                aStr = sEntry;
        }
        while (nIdx>0);
    }

    if ( cSelect )
    {
        if (aStr.isEmpty())
            aStr = OUString(cSelect);         // Ascii

        rCombo.set_entry_text(aStr);
    }
}

static sal_Unicode lcl_CharFromCombo(const weld::ComboBox& rCombo, std::u16string_view rList)
{
    sal_Unicode c = 0;
    OUString aStr = rCombo.get_active_text();
    if ( !aStr.isEmpty() && !rList.empty() )
    {
        sal_Int32 nIdx {0};
        OUString sToken {o3tl::getToken(rList, 0, '\t', nIdx)};
        while (nIdx>0)
        {
            if ( ScGlobal::GetTransliteration().isEqual( aStr, sToken ) )
            {
                sal_Int32 nTmpIdx {nIdx};
                c = static_cast<sal_Unicode>(o3tl::toInt32(o3tl::getToken(rList, 0, '\t', nTmpIdx)));
            }
            // Skip to next token at even position
            sToken = o3tl::getToken(rList, 1, '\t', nIdx);
        }
        if (!c)
        {
            sal_Unicode cFirst = aStr[0];
            // #i24235# first try the first character of the string directly
            if( (aStr.getLength() == 1) || (cFirst < '0') || (cFirst > '9') )
                c = cFirst;
            else    // keep old behaviour for compatibility (i.e. "39" -> "'")
                c = static_cast<sal_Unicode>(aStr.toInt32());       // Ascii
        }
    }
    return c;
}

static OUString lcl_GetConfigPath(ScImportAsciiCall eCall)
{
    switch(eCall)
    {
        case SC_IMPORTFILE:
            return u"Office.Calc/Dialogs/CSVImport"_ustr;
        case SC_PASTETEXT:
            return u"Office.Calc/Dialogs/ClipboardTextImport"_ustr;
        case SC_TEXTTOCOLUMNS:
        default:
            return u"Office.Calc/Dialogs/TextToColumnsImport"_ustr;
    }
}

static void lcl_LoadSeparators(ScImportAsciiCall eCall, OUString& rFieldSeparators, OUString& rTextSeparators,
                             bool& rMergeDelimiters, bool& rQuotedAsText, bool& rDetectSpecialNum, bool&&nbsp;rDetectScientificNum,
                             SeparatorType& rSepType, sal_Int32& rFromRow, rtl_TextEncoding& rEncoding,
                             sal_Int32& rLanguage, bool& rSkipEmptyCells, bool& rRemoveSpace,
                             bool& rEvaluateFormulas)
{
    ScLinkConfigItem aItem(lcl_GetConfigPath(eCall));
    const Sequence<OUString> aNames = aItem.GetNodeNames({});
    const Sequence<Any> aValues = aItem.GetProperties(aNames);

    rEncoding = RTL_TEXTENCODING_DONTKNOW;

    for (sal_Int32 i = 0; i < aNames.getLength(); ++i)
    {
        const OUString& name = aNames[i];
        const Any& value = aValues[i];
        if (!value.hasValue())
            continue;
        if (name == CSVIO_MergeDelimiters)
            rMergeDelimiters = ScUnoHelpFunctions::GetBoolFromAny(value);
        else if (name == CSVIO_RemoveSpace)
            rRemoveSpace = ScUnoHelpFunctions::GetBoolFromAny(value);
        else if (name == CSVIO_Separators)
            value >>= rFieldSeparators;
        else if (name == CSVIO_TextSeparators)
            value >>= rTextSeparators;
        else if (name == CSVIO_SeparatorType)
            rSepType = static_cast<SeparatorType>(ScUnoHelpFunctions::GetInt16FromAny(value));
        else if (name == CSVIO_EvaluateFormulas)
            rEvaluateFormulas = ScUnoHelpFunctions::GetBoolFromAny(value);
        else if (name == CSVIO_FromRow)
            value >>= rFromRow;
        else if (name == CSVIO_Encoding)
            value >>= rEncoding;
        else if (name == CSVIO_QuotedAsText)
            value >>= rQuotedAsText;
        else if (name == CSVIO_DetectSpecialNum)
            value >>= rDetectSpecialNum;
        else if (name == CSVIO_DetectScientificNum)
            value >>= rDetectScientificNum;
        else if (name == CSVIO_Language)
            value >>= rLanguage;
        else if (name == CSVIO_SkipEmptyCells)
            rSkipEmptyCells = ScUnoHelpFunctions::GetBoolFromAny(value);
    }
}

static void lcl_SaveSeparators(ScImportAsciiCall eCall,
    const OUString& sFieldSeparators, const OUString& sTextSeparators, bool bMergeDelimiters, bool bQuotedAsText,
    bool bDetectSpecialNum, bool bDetectScientificNum, SeparatorType rSepType, sal_Int32 nFromRow,
    rtl_TextEncoding eEncoding, sal_Int32 nLanguage, bool bSkipEmptyCells, bool bRemoveSpace, bool bEvaluateFormulas)
{
    ScLinkConfigItem aItem(lcl_GetConfigPath(eCall));
    std::unordered_map<OUString, Any> properties;

    for (const OUString& name : aItem.GetNodeNames({}))
    {
        if (name == CSVIO_MergeDelimiters)
            properties[name] <<= bMergeDelimiters;
        else if (name == CSVIO_RemoveSpace)
            properties[name] <<= bRemoveSpace;
        else if (name == CSVIO_Separators)
            properties[name] <<= sFieldSeparators;
        else if (name == CSVIO_TextSeparators)
            properties[name] <<= sTextSeparators;
        else if (name == CSVIO_EvaluateFormulas)
            properties[name] <<= bEvaluateFormulas;
        else if (name == CSVIO_SeparatorType)
            properties[name] <<= static_cast<sal_Int16>(rSepType);
        else if (name == CSVIO_FromRow)
            properties[name] <<= nFromRow;
        else if (name == CSVIO_Encoding)
            properties[name] <<= eEncoding;
        else if (name == CSVIO_QuotedAsText)
            properties[name] <<= bQuotedAsText;
        else if (name == CSVIO_DetectSpecialNum)
            properties[name] <<= bDetectSpecialNum;
        else if (name == CSVIO_DetectScientificNum)
            properties[name] <<= bDetectScientificNum;
        else if (name == CSVIO_Language)
            properties[name] <<= nLanguage;
        else if (name == CSVIO_SkipEmptyCells)
            properties[name] <<= bSkipEmptyCells;
    }

    aItem.PutProperties(comphelper::mapKeysToSequence(properties),
                        comphelper::mapValuesToSequence(properties));
}

ScImportAsciiDlg::ScImportAsciiDlg(weld::Window* pParent, std::u16string_view aDatName,
                                   SvStream* pInStream, ScImportAsciiCall eCall)
    : GenericDialogController(pParent, u"modules/scalc/ui/textimportcsv.ui"_ustr, u"TextImportCsvDialog"_ustr)
    , mpDatStream(pInStream)
    , mnStreamPos(pInStream ? pInStream->Tell() : 0)
    , mnStreamInitPos(mnStreamPos)
    , mnRowPosCount(0)
    , mcTextSep(ScAsciiOptions::cDefaultTextSep)
    , meDetectedCharSet(RTL_TEXTENCODING_DONTKNOW)
    , mbCharSetDetect(true)
    , meCall(eCall)
    , mxFtCharSet(m_xBuilder->weld_label(u"textcharset"_ustr))
    , mxLbCharSet(new SvxTextEncodingBox(m_xBuilder->weld_combo_box(u"charset"_ustr)))
    , mxFtDetectedCharSet(m_xBuilder->weld_label(u"textdetectedcharset"_ustr))
    , mxFtCustomLang(m_xBuilder->weld_label(u"textlanguage"_ustr))
    , mxLbCustomLang(new SvxLanguageBox(m_xBuilder->weld_combo_box(u"language"_ustr)))
    , mxFtRow(m_xBuilder->weld_label(u"textfromrow"_ustr))
    , mxNfRow(m_xBuilder->weld_spin_button(u"fromrow"_ustr))
    , mxRbDetectSep(m_xBuilder->weld_radio_button(u"todetectseparator"_ustr))
    , mxRbFixed(m_xBuilder->weld_radio_button(u"tofixedwidth"_ustr))
    , mxRbSeparated(m_xBuilder->weld_radio_button(u"toseparatedby"_ustr))
    , mxCkbTab(m_xBuilder->weld_check_button(u"tab"_ustr))
    , mxCkbSemicolon(m_xBuilder->weld_check_button(u"semicolon"_ustr))
    , mxCkbComma(m_xBuilder->weld_check_button(u"comma"_ustr))
    , mxCkbRemoveSpace(m_xBuilder->weld_check_button(u"removespace"_ustr))
    , mxCkbSpace(m_xBuilder->weld_check_button(u"space"_ustr))
    , mxCkbOther(m_xBuilder->weld_check_button(u"other"_ustr))
    , mxEdOther(m_xBuilder->weld_entry(u"inputother"_ustr))
    , mxCkbMergeDelimiters(m_xBuilder->weld_check_button(u"mergedelimiters"_ustr))
    , mxFtTextSep(m_xBuilder->weld_label(u"texttextdelimiter"_ustr))
    , mxCbTextSep(m_xBuilder->weld_combo_box(u"textdelimiter"_ustr))
    , mxCkbQuotedAsText(m_xBuilder->weld_check_button(u"quotedfieldastext"_ustr))
    , mxCkbDetectNumber(m_xBuilder->weld_check_button(u"detectspecialnumbers"_ustr))
    , mxCkbDetectScientificNumber(m_xBuilder->weld_check_button(u"detectscientificnumbers"_ustr))
    , mxCkbEvaluateFormulas(m_xBuilder->weld_check_button(u"evaluateformulas"_ustr))
    , mxCkbSkipEmptyCells(m_xBuilder->weld_check_button(u"skipemptycells"_ustr))
    , mxLbType(m_xBuilder->weld_combo_box(u"columntype"_ustr))
    , mxAltTitle(m_xBuilder->weld_label(u"textalttitle"_ustr))
    , mxTableBox(new ScCsvTableBox(*m_xBuilder))
    , mxCkbAlwaysShowOnImport(m_xBuilder->weld_check_button(u"alwaysshowonimport"_ustr))
{
    SvtViewOptions aDlgOpt(EViewType::Dialog, "TextImportCsvDialog");
    if (aDlgOpt.Exists())
        m_xDialog->set_window_state(aDlgOpt.GetWindowState());

    OUString aName = m_xDialog->get_title();
    switch (meCall)
    {
        case SC_TEXTTOCOLUMNS:
            m_xDialog->set_title(mxAltTitle->get_label());
            break;
        case SC_IMPORTFILE:
            if (!comphelper::LibreOfficeKit::isActive())
            {
                aName += OUString::Concat(" - [") + aDatName + "]";
                m_xDialog->set_title(aName);
            }
            mxCkbAlwaysShowOnImport->show();
            mxCkbAlwaysShowOnImport->set_active(
                utl::isShowFilterOptionsDialog(SC_TEXT_CSV_FILTER_NAME));
            break;
        default:
            break;
    }

    // To be able to prefill the correct values based on the file extension
    bool bIsTSV = (o3tl::endsWithIgnoreAsciiCase(aDatName, ".tsv") || o3tl::endsWithIgnoreAsciiCase(aDatName, ".tab"));

    // Default options are set in officecfg/registry/schema/org/openoffice/Office/Calc.xcs
    OUString sFieldSeparators(u",;\t"_ustr);
    OUString sTextSeparators(mcTextSep);
    bool bMergeDelimiters = false;
    SeparatorType eSepType = DETECT_SEPARATOR;
    bool bQuotedFieldAsText = false;
    bool bDetectSpecialNum = true;
    bool bDetectScientificNum = true;
    bool bEvaluateFormulas = (meCall != SC_IMPORTFILE);
    bool bSkipEmptyCells = true;
    bool bRemoveSpace = false;
    sal_Int32 nFromRow = 1;
    rtl_TextEncoding eEncoding = RTL_TEXTENCODING_DONTKNOW;
    sal_Int32 nLanguage = 0;

    lcl_LoadSeparators ( meCall, sFieldSeparators, sTextSeparators, bMergeDelimiters,
                         bQuotedFieldAsText, bDetectSpecialNum, bDetectScientificNum, eSepType, nFromRow,
                         eEncoding, nLanguage, bSkipEmptyCells, bRemoveSpace, bEvaluateFormulas);

    maFieldSeparators = sFieldSeparators;

    if( bMergeDelimiters && !bIsTSV )
        mxCkbMergeDelimiters->set_active(true);
    if (bQuotedFieldAsText)
        mxCkbQuotedAsText->set_active(true);
    if (bRemoveSpace)
        mxCkbRemoveSpace->set_active(true);
    if (bDetectSpecialNum)
    {
        mxCkbDetectNumber->set_active(true);
        bDetectScientificNum = true;
        mxCkbDetectScientificNumber->set_sensitive(false);
    }
    if (bDetectScientificNum)
        mxCkbDetectScientificNumber->set_active(true);
    if (bEvaluateFormulas)
        mxCkbEvaluateFormulas->set_active(true);
    if (bSkipEmptyCells)
        mxCkbSkipEmptyCells->set_active(true);
    if (eSepType == SeparatorType::FIXED)
    {
        if (bIsTSV)
        {
            eSepType = SeparatorType::SEPARATOR;
            mxRbSeparated->set_active(true);
        }
        else
            mxRbFixed->set_active(true);
    }
    else if (eSepType == SeparatorType::SEPARATOR)
        mxRbSeparated->set_active(true);
    else
        mxRbDetectSep->set_active(true);

    // Detect character set only once and then use it for "Detect" option.
    SvStreamEndian eEndian;
    SfxObjectShell::DetectCharSet(*mpDatStream, meDetectedCharSet, eEndian);
    if (meDetectedCharSet == RTL_TEXTENCODING_UNICODE)
        mpDatStream->SetEndian(eEndian);
    else if ( meDetectedCharSet == RTL_TEXTENCODING_DONTKNOW )
    {
        meDetectedCharSet = osl_getThreadTextEncoding();
        // Prefer UTF-8, as UTF-16 would have already been detected from the stream.
        // This gives a better chance that the file is going to be opened correctly.
        if ( meDetectedCharSet == RTL_TEXTENCODING_UNICODE && mpDatStream )
            meDetectedCharSet = RTL_TEXTENCODING_UTF8;
    }

    if (bIsTSV)
        SetSeparators('\t');
    else
        SetSeparators(0);

    // Get Separators from the dialog (empty are set from default)
    maFieldSeparators = GetActiveSeparators();

    // *** Separator characters ***
    lcl_FillCombo( *mxCbTextSep, SCSTR_TEXTSEP, mcTextSep );
    mxCbTextSep->set_entry_text(sTextSeparators);
    // tdf#69207 - use selected text delimiter to parse the provided data
    mcTextSep = lcl_CharFromCombo(*mxCbTextSep, SCSTR_TEXTSEP);

    Link<weld::Toggleable&,void> aSeparatorClickHdl =LINK( this, ScImportAsciiDlg, SeparatorClickHdl );
    Link<weld::Toggleable&,void> aOtherOptionsClickHdl =LINK( this, ScImportAsciiDlg, OtherOptionsClickHdl );
    mxCbTextSep->connect_changed( LINK( this, ScImportAsciiDlg, SeparatorComboBoxHdl ) );
    mxCkbTab->connect_toggled( aSeparatorClickHdl );
    mxCkbSemicolon->connect_toggled( aSeparatorClickHdl );
    mxCkbComma->connect_toggled( aSeparatorClickHdl );
    mxCkbMergeDelimiters->connect_toggled( aSeparatorClickHdl );
    mxCkbSpace->connect_toggled( aSeparatorClickHdl );
    mxCkbRemoveSpace->connect_toggled( aSeparatorClickHdl );
    mxCkbOther->connect_toggled( aSeparatorClickHdl );
    mxEdOther->connect_changed(LINK(this, ScImportAsciiDlg, SeparatorEditHdl));
    mxCkbQuotedAsText->connect_toggled( aOtherOptionsClickHdl );
    mxCkbDetectNumber->connect_toggled( aOtherOptionsClickHdl );
    mxCkbDetectScientificNumber->connect_toggled( aOtherOptionsClickHdl );
    mxCkbEvaluateFormulas->connect_toggled( aOtherOptionsClickHdl );
    mxCkbSkipEmptyCells->connect_toggled( aOtherOptionsClickHdl );

    // *** text encoding ListBox ***
    // all encodings allowed, including Unicode, but subsets are excluded
    mxLbCharSet->FillFromTextEncodingTable( true );
    // Insert one "SYSTEM" entry for compatibility in AsciiOptions and system
    // independent document linkage.
    mxLbCharSet->InsertTextEncoding( RTL_TEXTENCODING_DONTKNOW, ScResId( SCSTR_CHARSET_USER ) );
    // Insert one for detecting charset.
    mxLbCharSet->InsertTextEncoding( RTL_TEXTENCODING_USER_DETECTED, "- " + ScResId( SCSTR_AUTOMATIC ) + " -" );

    // Clipboard is always Unicode, and TextToColumns doesn't use encoding.
    if (meCall != SC_IMPORTFILE)
        eEncoding = RTL_TEXTENCODING_UNICODE;
    else if (eEncoding == RTL_TEXTENCODING_DONTKNOW)
        eEncoding = RTL_TEXTENCODING_USER_DETECTED;

    mxLbCharSet->SelectTextEncoding(eEncoding);

    SetSelectedCharSet();
    mxLbCharSet->connect_changed( LINK( this, ScImportAsciiDlg, CharSetHdl ) );

    mxLbCustomLang->SetLanguageList(
        SvxLanguageListFlags::ALL | SvxLanguageListFlags::ONLY_KNOWN, falsefalse);
    mxLbCustomLang->InsertLanguage(LANGUAGE_SYSTEM);
    mxLbCustomLang->set_active_id(static_cast<LanguageType>(nLanguage));

    // *** column type ListBox ***
    OUString aColumnUser( ScResId( SCSTR_COLUMN_USER ) );
    for (sal_Int32 nIdx {0}; nIdx>=0; )
    {
        mxLbType->append_text(aColumnUser.getToken(0, ';', nIdx));
    }

    mxLbType->connect_changed( LINK( this, ScImportAsciiDlg, LbColTypeHdl ) );
    mxLbType->set_sensitive(false);

    // *** table box preview ***
    mxTableBox->Init();
    mxTableBox->SetUpdateTextHdl( LINK( this, ScImportAsciiDlg, UpdateTextHdl ) );
    mxTableBox->InitTypes( *mxLbType );
    mxTableBox->SetColTypeHdl( LINK( this, ScImportAsciiDlg, ColTypeHdl ) );

    mxRbDetectSep->connect_toggled( LINK( this, ScImportAsciiDlg, RbSepFixHdl ) );
    mxRbSeparated->connect_toggled( LINK( this, ScImportAsciiDlg, RbSepFixHdl ) );
    mxRbFixed->connect_toggled( LINK( this, ScImportAsciiDlg, RbSepFixHdl ) );

    RbSepFix();

    UpdateVertical();

    mxTableBox->GetGrid().Execute( CSVCMD_NEWCELLTEXTS );

    if (nFromRow != 1)
    {
        mxNfRow->set_value(nFromRow);
        // tdf#163638 - show visual indicator for from rows
        mxTableBox->GetGrid().Execute(CSVCMD_SETFIRSTIMPORTLINE, nFromRow - 1);
    }
    mxNfRow->connect_value_changed(LINK(this, ScImportAsciiDlg, FirstRowHdl));

    if (meCall == SC_TEXTTOCOLUMNS)
    {
        m_xBuilder->weld_frame(u"frame1"_ustr)->hide(); // the whole "Import" section

        mxFtCharSet->set_sensitive(false);
        mxLbCharSet->set_sensitive(false);
        mxFtCustomLang->set_sensitive(false);
        mxLbCustomLang->set_active_id(LANGUAGE_SYSTEM);
        mxLbCustomLang->set_sensitive(false);
        mxFtRow->set_sensitive(false);
        mxNfRow->set_sensitive(false);

        // Quoted field as text option is not used for text-to-columns mode.
        mxCkbQuotedAsText->set_active(false);
        mxCkbQuotedAsText->set_sensitive(false);

        // Always detect special numbers for text-to-columns mode.
        mxCkbDetectNumber->set_active(true);
        mxCkbDetectNumber->set_sensitive(false);
        mxCkbDetectScientificNumber->set_active(true);
        mxCkbDetectScientificNumber->set_sensitive(false);
    }
    if (meCall == SC_IMPORTFILE)
    {
        //Empty cells in imported file are empty
        mxCkbSkipEmptyCells->set_active(false);
        mxCkbSkipEmptyCells->hide();
    }

    if (comphelper::LibreOfficeKit::isActive())
        m_xBuilder->weld_button(u"cancel"_ustr)->hide();
    m_xDialog->SetInstallLOKNotifierHdl(LINK(this, ScImportAsciiDlg, InstallLOKNotifierHdl));
}

IMPL_STATIC_LINK_NOARG(ScImportAsciiDlg, InstallLOKNotifierHdl, void*, vcl::ILibreOfficeKitNotifier*)
{
    return GetpApp();
}

ScImportAsciiDlg::~ScImportAsciiDlg()
{
    SvtViewOptions aDlgOpt(EViewType::Dialog, "TextImportCsvDialog");
    aDlgOpt.SetWindowState(m_xDialog->get_window_state(vcl::WindowDataMask::PosSize));
}

bool ScImportAsciiDlg::GetLine( sal_uLong nLine, OUString &rText, sal_Unicode& rcDetectSep )
{
    if (nLine >= ASCIIDLG_MAXROWS || !mpDatStream)
        return false;

    bool bRet = true;
    bool bFixed = mxRbFixed->get_active();

    if (!mpRowPosArray)
        mpRowPosArray.reset( new sal_uLong[ASCIIDLG_MAXROWS + 2] );

    if (!mnRowPosCount) // complete re-fresh
    {
        memset( mpRowPosArray.get(), 0, sizeof(mpRowPosArray[0]) * (ASCIIDLG_MAXROWS+2));

        Seek(0);
        mpDatStream->StartReadingUnicodeText( mpDatStream->GetStreamCharSet() );

        mnStreamPos = mpDatStream->Tell();
        mpRowPosArray[mnRowPosCount] = mnStreamPos;
    }

    if (nLine >= mnRowPosCount)
    {
        // need to work out some more line information
        do
        {
            if (!Seek(mpRowPosArray[mnRowPosCount]) || !mpDatStream->good())
            {
                bRet = false;
                break;
            }
            rText = ReadCsvLine(*mpDatStream, !bFixed, maFieldSeparators,
                    mcTextSep, rcDetectSep, kMaxEmbeddedLinefeeds);
            mnStreamPos = mpDatStream->Tell();
            mpRowPosArray[++mnRowPosCount] = mnStreamPos;
        } while (nLine >= mnRowPosCount && mpDatStream->good());
        if (mpDatStream->eof() && mnRowPosCount &&
                mnStreamPos == mpRowPosArray[mnRowPosCount-1])
        {
            // the very end, not even an empty line read
            bRet = false;
            --mnRowPosCount;
        }
    }
    else
    {
        Seek( mpRowPosArray[nLine]);
        rText = ReadCsvLine(*mpDatStream, !bFixed, maFieldSeparators, mcTextSep, rcDetectSep, kMaxEmbeddedLinefeeds);
        mnStreamPos = mpDatStream->Tell();
    }

    //  If the file content isn't unicode, ReadUniStringLine
    //  may try to seek beyond the file's end and cause a CANTSEEK error
    //  (depending on the stream type). The error code has to be cleared,
    //  or further read operations (including non-unicode) will fail.
    if ( mpDatStream->GetError() == ERRCODE_IO_CANTSEEK )
        mpDatStream->ResetError();

    ScImportExport::EmbeddedNullTreatment( rText);

    return bRet;
}

void ScImportAsciiDlg::GetOptions( ScAsciiOptions& rOpt )
{
    rOpt.SetCharSet( meCharSet );
    rOpt.SetCharSetSystem( mbCharSetSystem );
    rOpt.SetLanguage(mxLbCustomLang->get_active_id());
    rOpt.SetFixedLen( mxRbFixed->get_active() );
    rOpt.SetStartRow( mxNfRow->get_value() );
    mxTableBox->FillColumnData( rOpt );
    if( mxRbSeparated->get_active() || mxRbDetectSep->get_active())
    {
        rOpt.SetFieldSeps( GetActiveSeparators() );
        rOpt.SetMergeSeps( mxCkbMergeDelimiters->get_active() );
        rOpt.SetRemoveSpace( mxCkbRemoveSpace->get_active() );
        rOpt.SetTextSep( lcl_CharFromCombo( *mxCbTextSep, SCSTR_TEXTSEP ) );
    }

    rOpt.SetQuotedAsText(mxCkbQuotedAsText->get_active());
    rOpt.SetDetectSpecialNumber(mxCkbDetectNumber->get_active());
    rOpt.SetDetectScientificNumber(mxCkbDetectScientificNumber->get_active());
    rOpt.SetEvaluateFormulas(mxCkbEvaluateFormulas->get_active());
    rOpt.SetSkipEmptyCells(mxCkbSkipEmptyCells->get_active());
}

void ScImportAsciiDlg::SaveParameters()
{
    if (mxCkbAlwaysShowOnImport->get_visible())
    {
        bool value(mxCkbAlwaysShowOnImport->get_active());
        if (value != utl::isShowFilterOptionsDialog(SC_TEXT_CSV_FILTER_NAME))
        {
            auto pChange(comphelper::ConfigurationChanges::create());
            auto xFilterDialogSettings(
                utl::getSettingsForFilterOptions(SC_TEXT_CSV_FILTER_NAME, pChange));
            xFilterDialogSettings->setPropertyValue(u"show"_ustr, Any(value));
            pChange->commit();
        }
    }
    lcl_SaveSeparators(meCall, GetSeparators(), mxCbTextSep->get_active_text(), mxCkbMergeDelimiters->get_active(),
                     mxCkbQuotedAsText->get_active(), mxCkbDetectNumber->get_active(), mxCkbDetectScientificNumber->get_active(),
                     mxRbFixed->get_active() ? FIXED : (mxRbDetectSep->get_active() ? DETECT_SEPARATOR : SEPARATOR),
                     mxNfRow->get_value(),
                     mxLbCharSet->GetSelectTextEncoding(),
                     static_cast<sal_uInt16>(mxLbCustomLang->get_active_id()),
                     mxCkbSkipEmptyCells->get_active(), mxCkbRemoveSpace->get_active(),
                     mxCkbEvaluateFormulas->get_active());
}

void ScImportAsciiDlg::SetSeparators( sal_Unicode cSep )
{
    if (cSep)
    {
        // Exclusively set a separator, maFieldSeparators needs not be
        // modified, it's obtained by GetSeparators() after this call.
        static constexpr sal_Unicode aSeps[] = { '\t'';'','' ' };
        for (const sal_Unicode c : aSeps)
        {
            const bool bSet = (c == cSep);
            switch (c)
            {
                case '\t':  mxCkbTab->set_active(bSet);        break;
                case ';':   mxCkbSemicolon->set_active(bSet);  break;
                case ',':   mxCkbComma->set_active(bSet);      break;
                case ' ':   mxCkbSpace->set_active(bSet);      break;
            }
            if (bSet)
                cSep = 0;
        }
        if (cSep)
        {
            mxCkbOther->set_active(true);
            mxEdOther->set_text(OUStringChar(cSep));
        }
    }
    else
    {
        for (sal_Int32 i = 0; i < maFieldSeparators.getLength(); ++i)
        {
            switch (maFieldSeparators[i])
            {
                case '\t':  mxCkbTab->set_active(true);        break;
                case ';':   mxCkbSemicolon->set_active(true);  break;
                case ',':   mxCkbComma->set_active(true);      break;
                case ' ':   mxCkbSpace->set_active(true);      break;
                default:
                            mxCkbOther->set_active(true);
                            mxEdOther->set_text(mxEdOther->get_text() + OUStringChar(maFieldSeparators[i]));
            }
        }
    }
}

void ScImportAsciiDlg::SetSelectedCharSet()
{
    rtl_TextEncoding eOldCharSet = meCharSet;
    meCharSet = mxLbCharSet->GetSelectTextEncoding();
    mbCharSetDetect = (meCharSet == RTL_TEXTENCODING_USER_DETECTED);
    mbCharSetSystem = (meCharSet == RTL_TEXTENCODING_DONTKNOW);
    if (mbCharSetDetect)
    {
        meCharSet = meDetectedCharSet;
        mxFtDetectedCharSet->set_label(SvxTextEncodingTable::GetTextString(meCharSet));
    }
    else if( mbCharSetSystem )
    {
        meCharSet = osl_getThreadTextEncoding();
        mxFtDetectedCharSet->set_label(SvxTextEncodingTable::GetTextString(meCharSet));
    }
    else
        mxFtDetectedCharSet->set_label(SvxTextEncodingTable::GetTextString(meCharSet));

    if (eOldCharSet != meCharSet)
        DetectCsvSeparators();

    RbSepFix();
}

OUString ScImportAsciiDlg::GetSeparators() const
{
    OUString aSepChars;
    if( mxCkbTab->get_active() )
        aSepChars += "\t";
    if( mxCkbSemicolon->get_active() )
        aSepChars += ";";
    if( mxCkbComma->get_active() )
        aSepChars += ",";
    if( mxCkbSpace->get_active() )
        aSepChars += " ";
    if( mxCkbOther->get_active() )
        aSepChars += mxEdOther->get_text();
    return aSepChars;
}

OUString ScImportAsciiDlg::GetActiveSeparators() const
{
    if (mxRbSeparated->get_active())
        return GetSeparators();

    if (mxRbDetectSep->get_active())
        return maDetectedFieldSeps;

    return OUString();
}

void ScImportAsciiDlg::SetupSeparatorCtrls()
{
    bool bEnable = mxRbSeparated->get_active();
    mxCkbTab->set_sensitive( bEnable );
    mxCkbSemicolon->set_sensitive( bEnable );
    mxCkbComma->set_sensitive( bEnable );
    mxCkbSpace->set_sensitive( bEnable );
    mxCkbOther->set_sensitive( bEnable );
    mxEdOther->set_sensitive( bEnable );

    bEnable = bEnable || mxRbDetectSep->get_active();
    mxCkbRemoveSpace->set_sensitive( bEnable );
    mxCkbMergeDelimiters->set_sensitive( bEnable );
    mxFtTextSep->set_sensitive( bEnable );
    mxCbTextSep->set_sensitive( bEnable );

    OUString aSepName;
    if (maDetectedFieldSeps.isEmpty())
        aSepName += ScResId(SCSTR_NONE);
    else
    {
        for (int idx = 0; idx < maDetectedFieldSeps.getLength(); idx ++)
        {
            if (idx > 0)
                aSepName += u" ";

            if (maDetectedFieldSeps[idx] == u' ')
                aSepName += ScResId(SCSTR_FIELDSEP_SPACE);
            else if (maDetectedFieldSeps[idx] == u'\t')
                aSepName += ScResId(SCSTR_FIELDSEP_TAB);
            else
                aSepName += OUStringChar(maDetectedFieldSeps[idx]);
        }
    }
    mxRbDetectSep->set_label(ScResId(SCSTR_DETECTED).replaceFirst( "%1", aSepName));
}

void ScImportAsciiDlg::DetectCsvSeparators()
{
    mpDatStream->Seek(mnStreamInitPos);
    SfxObjectShell::DetectCsvSeparators(*mpDatStream, meCharSet, maDetectedFieldSeps, mcTextSep);
    mpDatStream->Seek(mnStreamPos);
}

void ScImportAsciiDlg::UpdateVertical()
{
    mnRowPosCount = 0;
    if (mpDatStream)
        mpDatStream->SetStreamCharSet(meCharSet);
}

void ScImportAsciiDlg::RbSepFix()
{
    weld::WaitObject aWaitObj(m_xDialog.get());
    if (mxRbSeparated->get_active() || mxRbDetectSep->get_active())
    {
        maFieldSeparators = GetActiveSeparators();
        if (mxTableBox->IsFixedWidthMode())
            mxTableBox->SetSeparatorsMode();
        else
            mxTableBox->Refresh();
    }
    else
        mxTableBox->SetFixedWidthMode();

    SetupSeparatorCtrls();
}

IMPL_LINK(ScImportAsciiDlg, RbSepFixHdl, weld::Toggleable&, rButton, void)
{
    if (!rButton.get_active())
        return;
    RbSepFix();
}

IMPL_LINK(ScImportAsciiDlg, SeparatorClickHdl, weld::Toggleable&, rCtrl, void)
{
    SeparatorHdl(&rCtrl);
}

IMPL_LINK( ScImportAsciiDlg, SeparatorComboBoxHdl, weld::ComboBox&, rCtrl, void )
{
    SeparatorHdl(&rCtrl);
}

IMPL_LINK( ScImportAsciiDlg, SeparatorEditHdl, weld::Entry&, rEdit, void )
{
    SeparatorHdl(&rEdit);
}

IMPL_LINK(ScImportAsciiDlg, OtherOptionsClickHdl, weld::Toggleable&, rCtrl, void)
{
    if (&rCtrl == mxCkbDetectNumber.get())
    {
        if (mxCkbDetectNumber->get_active())
        {
            mxCkbDetectScientificNumber->set_active(true);
            mxCkbDetectScientificNumber->set_sensitive(false);
        }
        else
            mxCkbDetectScientificNumber->set_sensitive(true);
        return;
    }
}

void ScImportAsciiDlg::SeparatorHdl(const weld::Widget* pCtrl)
{
    OSL_ENSURE( pCtrl, "ScImportAsciiDlg::SeparatorHdl - missing sender" );
    OSL_ENSURE( !mxRbFixed->get_active(), "ScImportAsciiDlg::SeparatorHdl - not allowed in fixed width" );

    /*  #i41550# First update state of the controls. The GetSeparators()
        function needs final state of the check boxes. */

    if (pCtrl == mxCkbOther.get() && mxCkbOther->get_active())
        mxEdOther->grab_focus();
    else if (pCtrl == mxEdOther.get())
        mxCkbOther->set_active(!mxEdOther->get_text().isEmpty());

    OUString aOldFldSeps( maFieldSeparators);
    sal_Unicode cOldSep = mcTextSep;
    mcTextSep = lcl_CharFromCombo( *mxCbTextSep, SCSTR_TEXTSEP );
    // Any separator changed may result in completely different lines due to
    // embedded line breaks.
    if (cOldSep != mcTextSep)
    {
        DetectCsvSeparators();

        SetupSeparatorCtrls();

        maFieldSeparators = GetActiveSeparators();
        if (aOldFldSeps != maFieldSeparators)
        {
            UpdateVertical();
            mxTableBox->Refresh();
            return;
        }
    }
    else
        maFieldSeparators = GetActiveSeparators();

    mxTableBox->GetGrid().Execute( CSVCMD_NEWCELLTEXTS );
}

IMPL_LINK_NOARG(ScImportAsciiDlg, CharSetHdl, weld::ComboBox&, void)
{
    if (mxLbCharSet->get_active() != -1)
    {
        weld::WaitObject aWaitObj(m_xDialog.get());
        rtl_TextEncoding eOldCharSet = meCharSet;
        SetSelectedCharSet();
        // switching char-set invalidates 8bit -> String conversions
        if (eOldCharSet != meCharSet)
            UpdateVertical();

        mxTableBox->GetGrid().Execute( CSVCMD_NEWCELLTEXTS );
    }
}

IMPL_LINK(ScImportAsciiDlg, FirstRowHdl, weld::SpinButton&, rNumField, void)
{
    mxTableBox->GetGrid().Execute( CSVCMD_SETFIRSTIMPORTLINE, rNumField.get_value() - 1);
}

IMPL_LINK(ScImportAsciiDlg, LbColTypeHdl, weld::ComboBox&, rListBox, void)
{
    if (&rListBox == mxLbType.get())
        mxTableBox->GetGrid().Execute(CSVCMD_SETCOLUMNTYPE, rListBox.get_active());
}

IMPL_LINK_NOARG(ScImportAsciiDlg, UpdateTextHdl, ScCsvTableBox&, void)
{
    sal_Unicode cDetectSep = 0xffff;

    sal_Int32 nBaseLine = mxTableBox->GetGrid().GetFirstVisLine();
    sal_Int32 nRead = mxTableBox->GetGrid().GetVisLineCount();
    // If mnRowPosCount==0, this is an initializing call, read ahead for row
    // count and resulting scroll bar size and position to be able to scroll at
    // all. When adding lines, read only the amount of next lines to be
    // displayed.
    if (!mnRowPosCount || nRead > CSV_PREVIEW_LINES)
        nRead = CSV_PREVIEW_LINES;

    sal_Int32 i;
    for (i = 0; i < nRead; i++)
    {
        if (!GetLine( nBaseLine + i, maPreviewLine[i], cDetectSep))
            break;
    }
    for (; i < CSV_PREVIEW_LINES; i++)
        maPreviewLine[i].clear();


    mxTableBox->GetGrid().Execute( CSVCMD_SETLINECOUNT, mnRowPosCount);
    bool bMergeSep = mxCkbMergeDelimiters->get_active();
    bool bRemoveSpace = mxCkbRemoveSpace->get_active();
    mxTableBox->SetUniStrings( maPreviewLine, maFieldSeparators, mcTextSep, bMergeSep, bRemoveSpace );
}

IMPL_LINK( ScImportAsciiDlg, ColTypeHdl, ScCsvTableBox&, rTableBox, void )
{
    sal_Int32 nType = rTableBox.GetSelColumnType();
    sal_Int32 nTypeCount = mxLbType->get_count();
    bool bEmpty = (nType == CSV_TYPE_MULTI);
    bool bEnable = ((0 <= nType) && (nType < nTypeCount)) || bEmpty;

    mxLbType->set_sensitive( bEnable );

    if (bEmpty)
        mxLbType->set_active(-1);
    else if (bEnable)
        mxLbType->set_active(nType);
}

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

Messung V0.5
C=93 H=98 G=95

¤ Dauer der Verarbeitung: 0.14 Sekunden  (vorverarbeitet)  ¤

*© 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.