1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <dbinsdlg.hxx>
24 #include <hintids.hxx>
25 #include <com/sun/star/container/XNameAccess.hpp>
26 #include <com/sun/star/sdbc/XDataSource.hpp>
27 #include <com/sun/star/sdbc/XRow.hpp>
28 #include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
29 #include <com/sun/star/sdbcx/XRowLocate.hpp>
30 #include <com/sun/star/sdb/XQueriesSupplier.hpp>
31 #include <com/sun/star/sdb/XColumn.hpp>
32 #include <com/sun/star/sdbc/DataType.hpp>
33 #include <com/sun/star/beans/XPropertySet.hpp>
34 #include <com/sun/star/util/NumberFormatter.hpp>
35 #include <com/sun/star/util/XNumberFormatTypes.hpp>
36 #include <comphelper/processfactory.hxx>
37 #include <comphelper/sequence.hxx>
38 #include <comphelper/types.hxx>
39 #include <svl/numuno.hxx>
40 #include <svl/numformat.hxx>
41 #include <svl/stritem.hxx>
42 #include <comphelper/diagnose_ex.hxx>
44 #include <vcl/mnemonic.hxx>
45 #include <svl/style.hxx>
46 #include <svl/zformat.hxx>
47 #include <sfx2/htmlmode.hxx>
48 #include <svl/itemset.hxx>
49 #include <editeng/brushitem.hxx>
50 #include <editeng/boxitem.hxx>
51 #include <unotools/collatorwrapper.hxx>
52 #include <fmtclds.hxx>
54 #include <uiitems.hxx>
55 #include <viewopt.hxx>
60 #include <tblafmt.hxx>
61 #include <cellatr.hxx>
62 #include <swtablerep.hxx>
67 #include <swmodule.hxx>
68 #include <poolfmt.hxx>
69 #include <connectivity/dbtools.hxx>
72 #include <SwStyleNameMapper.hxx>
74 #include <swabstdlg.hxx>
75 #include <strings.hrc>
76 #include <IDocumentMarkAccess.hxx>
78 #include <o3tl/any.hxx>
81 #include <string_view>
83 #include <swuiexp.hxx>
85 using namespace ::dbtools
;
86 using namespace ::com::sun::star
;
87 using namespace ::com::sun::star::beans
;
88 using namespace ::com::sun::star::container
;
89 using namespace ::com::sun::star::lang
;
90 using namespace ::com::sun::star::sdb
;
91 using namespace ::com::sun::star::sdbc
;
92 using namespace ::com::sun::star::sdbcx
;
93 using namespace ::com::sun::star::uno
;
95 const char cDBFieldStart
= '<';
96 const char cDBFieldEnd
= '>';
98 // Helper structure for adding database rows as fields or text
101 const enum class Type
{ FILLTEXT
, COL_FIELD
, COL_TEXT
, SPLITPARA
} eColType
;
108 const SwInsDBColumn
* pColInfo
;
110 DB_Column() : eColType(Type::SPLITPARA
),
115 explicit DB_Column( const OUString
& rText
)
116 : eColType(Type::FILLTEXT
),
117 pText(new OUString(rText
)),
121 DB_Column( const SwInsDBColumn
& rInfo
, sal_uInt32 nFormat_
)
122 : eColType(Type::COL_TEXT
),
127 DB_Column( const SwInsDBColumn
& rInfo
, SwDBField
& rField
)
128 : eColType(Type::COL_FIELD
),
135 if( Type::COL_FIELD
== eColType
)
137 else if( Type::FILLTEXT
== eColType
)
144 struct DB_ColumnConfigData
146 SwInsDBColumns aDBColumns
;
150 OUString sTAutoFormatNm
;
156 DB_ColumnConfigData(DB_ColumnConfigData
const&) = delete;
157 DB_ColumnConfigData
& operator=(DB_ColumnConfigData
const&) = delete;
159 DB_ColumnConfigData()
161 bIsTable
= bIsHeadlineOn
= true;
162 bIsField
= bIsEmptyHeadln
= false;
168 bool SwInsDBColumn::operator<( const SwInsDBColumn
& rCmp
) const
170 return 0 > GetAppCollator().compareString( sColumn
, rCmp
.sColumn
);
173 SwInsertDBColAutoPilot::SwInsertDBColAutoPilot( SwView
& rView
,
174 Reference
<XDataSource
> const & xDataSource
,
175 Reference
<sdbcx::XColumnsSupplier
> const & xColSupp
,
177 : SfxDialogController(rView
.GetWindow()->GetFrameWeld(), "modules/swriter/ui/insertdbcolumnsdialog.ui", "InsertDbColumnsDialog")
178 , ConfigItem("Office.Writer/InsertData/DataSet", ConfigItemMode::NONE
)
179 , m_aDBData(std::move(aData
))
180 , m_sNoTmpl(SwResId(SW_STR_NONE
))
182 , m_xRbAsTable(m_xBuilder
->weld_radio_button("astable"))
183 , m_xRbAsField(m_xBuilder
->weld_radio_button("asfields"))
184 , m_xRbAsText(m_xBuilder
->weld_radio_button("astext"))
185 , m_xHeadFrame(m_xBuilder
->weld_frame("dbframe"))
186 , m_xLbTableDbColumn(m_xBuilder
->weld_tree_view("tabledbcols"))
187 , m_xLbTextDbColumn(m_xBuilder
->weld_tree_view("tabletxtcols"))
188 , m_xFormatFrame(m_xBuilder
->weld_frame("formatframe"))
189 , m_xRbDbFormatFromDb(m_xBuilder
->weld_radio_button("fromdatabase"))
190 , m_xRbDbFormatFromUsr(m_xBuilder
->weld_radio_button("userdefined"))
191 , m_xLbDbFormatFromUsr(new NumFormatListBox(m_xBuilder
->weld_combo_box("numformat")))
192 , m_xIbDbcolToEdit(m_xBuilder
->weld_button("toedit"))
193 , m_xEdDbText(m_xBuilder
->weld_text_view("textview"))
194 , m_xFtDbParaColl(m_xBuilder
->weld_label("parastylelabel"))
195 , m_xLbDbParaColl(m_xBuilder
->weld_combo_box("parastyle"))
196 , m_xIbDbcolAllTo(m_xBuilder
->weld_button("oneright"))
197 , m_xIbDbcolOneTo(m_xBuilder
->weld_button("allright"))
198 , m_xIbDbcolOneFrom(m_xBuilder
->weld_button("oneleft"))
199 , m_xIbDbcolAllFrom(m_xBuilder
->weld_button("allleft"))
200 , m_xFtTableCol(m_xBuilder
->weld_label("tablecolft"))
201 , m_xLbTableCol(m_xBuilder
->weld_tree_view("tablecols"))
202 , m_xCbTableHeadon(m_xBuilder
->weld_check_button("tableheading"))
203 , m_xRbHeadlColnms(m_xBuilder
->weld_radio_button("columnname"))
204 , m_xRbHeadlEmpty(m_xBuilder
->weld_radio_button("rowonly"))
205 , m_xPbTableFormat(m_xBuilder
->weld_button("tableformat"))
206 , m_xPbTableAutofmt(m_xBuilder
->weld_button("autoformat"))
208 m_xEdDbText
->set_size_request(m_xEdDbText
->get_approximate_digit_width() * 40, -1);
209 m_xLbDbParaColl
->make_sorted();
211 m_nGBFormatLen
= m_xFormatFrame
->get_label().getLength();
215 SwWrtShell
& rSh
= m_pView
->GetWrtShell();
216 SvNumberFormatter
* pNumFormatr
= rSh
.GetNumberFormatter();
217 rtl::Reference
<SvNumberFormatsSupplierObj
> pNumFormat
= new SvNumberFormatsSupplierObj( pNumFormatr
);
218 Reference
< util::XNumberFormats
> xDocNumberFormats
= pNumFormat
->getNumberFormats();
219 Reference
< util::XNumberFormatTypes
> xDocNumberFormatTypes(xDocNumberFormats
, UNO_QUERY
);
221 Reference
<XPropertySet
> xSourceProps(xDataSource
, UNO_QUERY
);
222 Reference
< util::XNumberFormats
> xNumberFormats
;
223 if(xSourceProps
.is())
225 Any aFormats
= xSourceProps
->getPropertyValue("NumberFormatsSupplier");
226 if(aFormats
.hasValue())
228 Reference
< util::XNumberFormatsSupplier
> xSuppl
;
232 xNumberFormats
= xSuppl
->getNumberFormats( );
236 Reference
<XNameAccess
> xCols
= xColSupp
->getColumns();
237 const Sequence
<OUString
> aColNames
= xCols
->getElementNames();
238 for (const OUString
& rColName
: aColNames
)
240 std::unique_ptr
<SwInsDBColumn
> pNew(new SwInsDBColumn( rColName
));
241 Any aCol
= xCols
->getByName(rColName
);
242 Reference
<XPropertySet
> xCol
;
244 Any aType
= xCol
->getPropertyValue("Type");
245 sal_Int32 eDataType
= 0;
250 case DataType::BOOLEAN
:
251 case DataType::TINYINT
:
252 case DataType::SMALLINT
:
253 case DataType::INTEGER
:
254 case DataType::BIGINT
:
255 case DataType::FLOAT
:
257 case DataType::DOUBLE
:
258 case DataType::NUMERIC
:
259 case DataType::DECIMAL
:
262 case DataType::TIMESTAMP
:
264 pNew
->bHasFormat
= true;
265 Any aFormat
= xCol
->getPropertyValue("FormatKey");
266 if(aFormat
.hasValue())
268 sal_Int32 nFormat
= 0;
270 if(xNumberFormats
.is())
274 Reference
<XPropertySet
> xNumProps
= xNumberFormats
->getByKey( nFormat
);
275 Any aFormatVal
= xNumProps
->getPropertyValue("FormatString");
276 Any aLocale
= xNumProps
->getPropertyValue("Locale");
278 aFormatVal
>>= sFormat
;
281 sal_Int32 nKey
= xDocNumberFormats
->queryKey( sFormat
, aLoc
, true);
284 nKey
= xDocNumberFormats
->addNew( sFormat
, aLoc
);
286 pNew
->nDBNumFormat
= nKey
;
288 catch (const Exception
&)
290 OSL_FAIL("illegal number format key");
296 pNew
->nDBNumFormat
= getDefaultNumberFormat(xCol
,
297 xDocNumberFormatTypes
, LanguageTag( rSh
.GetCurLang() ).getLocale());
303 if( !m_aDBColumns
.insert( std::move(pNew
) ).second
)
305 OSL_ENSURE( false, "Spaltenname mehrfach vergeben?" );
310 // fill paragraph templates-ListBox
312 SfxStyleSheetBasePool
* pPool
= m_pView
->GetDocShell()->GetStyleSheetPool();
313 m_xLbDbParaColl
->append_text( m_sNoTmpl
);
315 const SfxStyleSheetBase
* pBase
= pPool
->First(SfxStyleFamily::Para
);
318 m_xLbDbParaColl
->append_text( pBase
->GetName() );
319 pBase
= pPool
->Next();
321 m_xLbDbParaColl
->set_active( 0 );
324 // when the cursor is inside of a table, table must NEVER be selectable
325 if( m_pView
->GetWrtShell().GetTableFormat() )
327 m_xRbAsField
->set_active(true);
328 m_xRbAsTable
->set_sensitive(false);
329 m_xRbDbFormatFromDb
->set_active(true);
333 m_xRbAsTable
->set_active(true);
334 m_xRbDbFormatFromDb
->set_active(true);
335 m_xIbDbcolOneFrom
->set_sensitive( false );
336 m_xIbDbcolAllFrom
->set_sensitive( false );
339 // by default, select header button
340 m_xRbHeadlColnms
->set_active(true);
341 m_xRbHeadlEmpty
->set_active(false);
343 m_xRbAsTable
->connect_toggled( LINK(this, SwInsertDBColAutoPilot
, PageHdl
));
344 m_xRbAsField
->connect_toggled( LINK(this, SwInsertDBColAutoPilot
, PageHdl
));
345 m_xRbAsText
->connect_toggled( LINK(this, SwInsertDBColAutoPilot
, PageHdl
));
347 m_xRbDbFormatFromDb
->connect_toggled( LINK(this, SwInsertDBColAutoPilot
, DBFormatHdl
));
348 m_xRbDbFormatFromUsr
->connect_toggled( LINK(this, SwInsertDBColAutoPilot
, DBFormatHdl
));
350 m_xPbTableFormat
->connect_clicked(LINK(this, SwInsertDBColAutoPilot
, TableFormatHdl
));
351 m_xPbTableAutofmt
->connect_clicked(LINK(this, SwInsertDBColAutoPilot
, AutoFormatHdl
));
353 m_xIbDbcolAllTo
->connect_clicked( LINK(this, SwInsertDBColAutoPilot
, TableToFromHdl
));
354 m_xIbDbcolOneTo
->connect_clicked( LINK(this, SwInsertDBColAutoPilot
, TableToFromHdl
));
355 m_xIbDbcolOneFrom
->connect_clicked( LINK(this, SwInsertDBColAutoPilot
, TableToFromHdl
));
356 m_xIbDbcolAllFrom
->connect_clicked( LINK(this, SwInsertDBColAutoPilot
, TableToFromHdl
));
357 m_xIbDbcolToEdit
->connect_clicked( LINK(this, SwInsertDBColAutoPilot
, TableToFromHdl
));
359 m_xCbTableHeadon
->connect_toggled( LINK(this, SwInsertDBColAutoPilot
, HeaderHdl
));
361 m_xLbTextDbColumn
->connect_changed( LINK( this, SwInsertDBColAutoPilot
, TVSelectHdl
));
362 m_xLbTableDbColumn
->connect_changed( LINK( this, SwInsertDBColAutoPilot
, TVSelectHdl
));
363 m_xLbDbFormatFromUsr
->connect_changed( LINK( this, SwInsertDBColAutoPilot
, CBSelectHdl
));
364 m_xLbTableCol
->connect_changed( LINK( this, SwInsertDBColAutoPilot
, TVSelectHdl
));
366 m_xLbTextDbColumn
->connect_row_activated( LINK( this, SwInsertDBColAutoPilot
, DblClickHdl
));
367 m_xLbTableDbColumn
->connect_row_activated( LINK( this, SwInsertDBColAutoPilot
, DblClickHdl
));
368 m_xLbTableCol
->connect_row_activated( LINK( this, SwInsertDBColAutoPilot
, DblClickHdl
));
370 for( size_t n
= 0; n
< m_aDBColumns
.size(); ++n
)
372 const OUString
& rS
= m_aDBColumns
[ n
]->sColumn
;
373 m_xLbTableDbColumn
->append_text(rS
);
374 m_xLbTextDbColumn
->append_text(rS
);
376 m_xLbTextDbColumn
->select(0);
377 m_xLbTableDbColumn
->select(0);
379 // read configuration
382 // lock size to widest config
383 m_xHeadFrame
->set_size_request(m_xHeadFrame
->get_preferred_size().Width(), -1);
384 // initialise Controls:
385 PageHdl(m_xRbAsTable
->get_active() ? *m_xRbAsTable
: *m_xRbAsField
);
388 SwInsertDBColAutoPilot::~SwInsertDBColAutoPilot()
392 IMPL_LINK( SwInsertDBColAutoPilot
, PageHdl
, weld::Toggleable
&, rButton
, void )
394 if (!rButton
.get_active())
397 bool bShowTable
= m_xRbAsTable
->get_active();
399 weld::RadioButton
& rRadio
= dynamic_cast<weld::RadioButton
&>(rButton
);
400 m_xHeadFrame
->set_label(MnemonicGenerator::EraseAllMnemonicChars(rRadio
.get_label().replace('_', '~')));
402 m_xLbTextDbColumn
->set_visible( !bShowTable
);
403 m_xIbDbcolToEdit
->set_visible( !bShowTable
);
404 m_xEdDbText
->set_visible( !bShowTable
);
405 m_xFtDbParaColl
->set_visible( !bShowTable
);
406 m_xLbDbParaColl
->set_visible( !bShowTable
);
408 m_xLbTableDbColumn
->set_visible( bShowTable
);
409 m_xIbDbcolAllTo
->set_visible( bShowTable
);
410 m_xIbDbcolOneTo
->set_visible( bShowTable
);
411 m_xIbDbcolOneFrom
->set_visible( bShowTable
);
412 m_xIbDbcolAllFrom
->set_visible( bShowTable
);
413 m_xFtTableCol
->set_visible( bShowTable
);
414 m_xLbTableCol
->set_visible( bShowTable
);
415 m_xCbTableHeadon
->set_visible( bShowTable
);
416 m_xRbHeadlColnms
->set_visible( bShowTable
);
417 m_xRbHeadlEmpty
->set_visible( bShowTable
);
418 m_xPbTableFormat
->set_visible( bShowTable
);
419 m_xPbTableAutofmt
->set_visible( bShowTable
);
422 m_xPbTableFormat
->set_sensitive( 0 != m_xLbTableCol
->n_children() );
424 TVSelectHdl( bShowTable
? *m_xLbTableDbColumn
: *m_xLbTextDbColumn
);
427 IMPL_LINK( SwInsertDBColAutoPilot
, DBFormatHdl
, weld::Toggleable
&, rButton
, void )
429 if (!rButton
.get_active())
432 weld::TreeView
& rBox
= m_xRbAsTable
->get_active()
433 ? ( m_xLbTableCol
->get_id(0).isEmpty()
434 ? *m_xLbTableDbColumn
436 : *m_xLbTextDbColumn
;
438 SwInsDBColumn
aSrch(rBox
.get_selected_text());
439 SwInsDBColumns::const_iterator it
= m_aDBColumns
.find( &aSrch
);
441 bool bFromDB
= m_xRbDbFormatFromDb
->get_active();
442 (*it
)->bIsDBFormat
= bFromDB
;
443 m_xLbDbFormatFromUsr
->set_sensitive( !bFromDB
);
446 IMPL_LINK( SwInsertDBColAutoPilot
, TableToFromHdl
, weld::Button
&, rButton
, void )
448 bool bChgEnable
= true, bEnableTo
= true, bEnableFrom
= true;
450 if( &rButton
== m_xIbDbcolAllTo
.get() )
454 sal_Int32 n
, nInsPos
= m_xLbTableCol
->get_selected_index(),
455 nCnt
= m_xLbTableDbColumn
->n_children();
457 m_xLbTableDbColumn
->unselect_all();
459 m_xLbTableDbColumn
->freeze();
460 m_xLbTableCol
->freeze();
463 for( n
= 0; n
< nCnt
; ++n
)
464 m_xLbTableCol
->append_text(m_xLbTableDbColumn
->get_text(n
));
466 for( n
= 0; n
< nCnt
; ++n
, ++nInsPos
)
467 m_xLbTableCol
->insert_text(nInsPos
, m_xLbTableDbColumn
->get_text(n
));
468 m_xLbTableDbColumn
->clear();
470 m_xLbTableDbColumn
->thaw();
471 m_xLbTableCol
->thaw();
473 m_xLbTableCol
->select(nInsPos
);
475 else if( &rButton
== m_xIbDbcolOneTo
.get() &&
476 m_xLbTableDbColumn
->get_selected_index() != -1 )
478 sal_Int32 nInsPos
= m_xLbTableCol
->get_selected_index(),
479 nDelPos
= m_xLbTableDbColumn
->get_selected_index();
480 m_xLbTableCol
->insert_text(nInsPos
, m_xLbTableDbColumn
->get_text(nDelPos
));
481 m_xLbTableDbColumn
->remove(nDelPos
);
483 m_xLbTableCol
->select(nInsPos
);
484 if (nDelPos
>= m_xLbTableDbColumn
->n_children())
485 nDelPos
= m_xLbTableDbColumn
->n_children() - 1;
486 m_xLbTableDbColumn
->select(nDelPos
);
488 bEnableTo
= 0 != m_xLbTableDbColumn
->n_children();
490 else if( &rButton
== m_xIbDbcolOneFrom
.get() )
492 if (m_xLbTableCol
->get_selected_index() != -1)
495 nDelPos
= m_xLbTableCol
->get_selected_index();
497 // look for the right InsertPos!!
498 SwInsDBColumn
aSrch(m_xLbTableCol
->get_text(nDelPos
));
499 SwInsDBColumns::const_iterator it
= m_aDBColumns
.find( &aSrch
);
500 if( it
== m_aDBColumns
.begin() || (it
+1) == m_aDBColumns
.end() )
501 nInsPos
= it
- m_aDBColumns
.begin();
505 while( ++it
!= m_aDBColumns
.end() &&
506 -1 == (nInsPos
= m_xLbTableDbColumn
->
507 find_text( (*it
)->sColumn
)) )
511 m_xLbTableDbColumn
->insert_text(nInsPos
, aSrch
.sColumn
);
512 m_xLbTableCol
->remove( nDelPos
);
514 if (nInsPos
>= m_xLbTableDbColumn
->n_children())
515 nInsPos
= m_xLbTableDbColumn
->n_children() - 1;
516 m_xLbTableDbColumn
->select(nInsPos
);
518 if (nDelPos
>= m_xLbTableCol
->n_children())
519 nDelPos
= m_xLbTableCol
->n_children() - 1;
520 m_xLbTableCol
->select(nDelPos
);
523 bEnableTo
= 0 != m_xLbTableDbColumn
->n_children();
525 bEnableFrom
= 0 != m_xLbTableCol
->n_children();
527 else if( &rButton
== m_xIbDbcolAllFrom
.get() )
531 m_xLbTableDbColumn
->freeze();
532 m_xLbTableCol
->freeze();
534 m_xLbTableDbColumn
->clear();
535 m_xLbTableCol
->clear();
536 for (size_t n
= 0; n
< m_aDBColumns
.size(); ++n
)
537 m_xLbTableDbColumn
->append_text(m_aDBColumns
[n
]->sColumn
);
539 m_xLbTableDbColumn
->thaw();
540 m_xLbTableCol
->thaw();
542 m_xLbTableDbColumn
->select(0);
544 else if( &rButton
== m_xIbDbcolToEdit
.get() )
547 // move data to Edit:
548 OUString
aField(m_xLbTextDbColumn
->get_selected_text());
549 if( !aField
.isEmpty() )
551 OUString
aStr( m_xEdDbText
->get_text() );
552 int nStartPos
, nEndPos
;
553 m_xEdDbText
->get_selection_bounds(nStartPos
, nEndPos
);
554 sal_Int32 nPos
= std::min(nStartPos
, nEndPos
);
555 sal_Int32 nMax
= std::max(nStartPos
, nEndPos
);
556 const sal_Int32 nSel
= nMax
- nPos
;
558 // first delete the existing selection
559 aStr
= aStr
.replaceAt( nPos
, nSel
, u
"" );
561 aField
= OUStringChar(cDBFieldStart
) + aField
+ OUStringChar(cDBFieldEnd
);
562 if( !aStr
.isEmpty() )
564 if( nPos
) // one blank in front
566 sal_Unicode c
= aStr
[ nPos
-1 ];
567 if( '\n' != c
&& '\r' != c
)
568 aField
= " " + aField
;
570 if( nPos
< aStr
.getLength() ) // one blank behind
572 sal_Unicode c
= aStr
[ nPos
];
573 if( '\n' != c
&& '\r' != c
)
578 m_xEdDbText
->set_text( aStr
.replaceAt( nPos
, 0, aField
) );
579 nPos
+= aField
.getLength();
580 m_xEdDbText
->select_region(nPos
, nPos
);
587 m_xIbDbcolOneTo
->set_sensitive( bEnableTo
);
588 m_xIbDbcolAllTo
->set_sensitive( bEnableTo
);
589 m_xIbDbcolOneFrom
->set_sensitive( bEnableFrom
);
590 m_xIbDbcolAllFrom
->set_sensitive( bEnableFrom
);
592 m_xRbDbFormatFromDb
->set_sensitive( false );
593 m_xRbDbFormatFromUsr
->set_sensitive( false );
594 m_xLbDbFormatFromUsr
->set_sensitive( false );
596 m_xPbTableFormat
->set_sensitive( bEnableFrom
);
599 IMPL_LINK(SwInsertDBColAutoPilot
, DblClickHdl
, weld::TreeView
&, rBox
, bool)
601 weld::Button
* pButton
= nullptr;
602 if( &rBox
== m_xLbTextDbColumn
.get() )
603 pButton
= m_xIbDbcolToEdit
.get();
604 else if( &rBox
== m_xLbTableDbColumn
.get() && m_xIbDbcolOneTo
->get_sensitive() )
605 pButton
= m_xIbDbcolOneTo
.get();
606 else if( &rBox
== m_xLbTableCol
.get() && m_xIbDbcolOneFrom
->get_sensitive() )
607 pButton
= m_xIbDbcolOneFrom
.get();
610 TableToFromHdl(*pButton
);
615 IMPL_LINK_NOARG(SwInsertDBColAutoPilot
, TableFormatHdl
, weld::Button
&, void)
617 SwWrtShell
& rSh
= m_pView
->GetWrtShell();
618 bool bNewSet
= false;
622 m_pTableSet
.reset(new SfxItemSet( rSh
.GetAttrPool(), SwuiGetUITableAttrRange() ));
624 // At first acquire the simple attributes
625 m_pTableSet
->Put( SfxStringItem( FN_PARAM_TABLE_NAME
, rSh
.GetUniqueTableName() ));
626 m_pTableSet
->Put( SfxUInt16Item( FN_PARAM_TABLE_HEADLINE
, 1 ) );
628 m_pTableSet
->Put( SfxUInt16Item( SID_BACKGRND_DESTINATION
,
629 rSh
.GetViewOptions()->GetTableDest() ));
631 SvxBrushItem
aBrush( RES_BACKGROUND
);
632 m_pTableSet
->Put( aBrush
);
633 aBrush
.SetWhich(SID_ATTR_BRUSH_ROW
);
634 m_pTableSet
->Put( aBrush
);
635 aBrush
.SetWhich(SID_ATTR_BRUSH_TABLE
);
636 m_pTableSet
->Put( aBrush
);
638 SvxBoxInfoItem
aBoxInfo( SID_ATTR_BORDER_INNER
);
639 // table variant, when multiple table cells are selected
640 aBoxInfo
.SetTable( true );
641 // always show gap field
642 aBoxInfo
.SetDist( true);
643 // set minimum size in tables and paragraphs
644 aBoxInfo
.SetMinDist( false );
645 // always set default-gap
646 aBoxInfo
.SetDefDist( MIN_BORDER_DIST
);
647 // Single lines can have DontCare-status only in tables
648 aBoxInfo
.SetValid( SvxBoxInfoItemValidFlags::DISABLE
);
649 m_pTableSet
->Put( aBoxInfo
);
651 SwGetCurColNumPara aPara
;
652 const sal_uInt16 nNum
= rSh
.GetCurColNum( &aPara
);
657 nWidth
= aPara
.pPrtRect
->Width();
658 const SwFormatCol
& rCol
= aPara
.pFrameFormat
->GetCol();
659 const SwColumns
& rCols
= rCol
.GetColumns();
661 // initialise nStart and nEnd for nNum == 0
662 tools::Long nWidth1
= 0,
665 for( sal_uInt16 i
= 0; i
< nNum
; ++i
)
667 const SwColumn
* pCol
= &rCols
[i
];
668 nStart1
= pCol
->GetLeft() + nWidth1
;
669 nWidth1
+= static_cast<tools::Long
>(rCol
.CalcColWidth( i
, o3tl::narrowing
<sal_uInt16
>(nWidth
) ));
670 nEnd1
= nWidth1
- pCol
->GetRight();
672 if(nStart1
|| nEnd1
!= nWidth
)
673 nWidth
= nEnd1
- nStart1
;
676 nWidth
= rSh
.GetAnyCurRect(
677 (FrameTypeFlags::FLY_ANY
& rSh
.GetFrameType( nullptr, true ))
678 ? CurRectType::FlyEmbeddedPrt
679 : CurRectType::PagePrt
).Width();
682 aTabCols
.SetRight( nWidth
);
683 aTabCols
.SetRightMax( nWidth
);
684 m_pRep
.reset(new SwTableRep( aTabCols
));
685 m_pRep
->SetAlign( text::HoriOrientation::NONE
);
686 m_pRep
->SetSpace( nWidth
);
687 m_pRep
->SetWidth( nWidth
);
688 m_pRep
->SetWidthPercent( 100 );
689 m_pTableSet
->Put( SwPtrItem( FN_TABLE_REP
, m_pRep
.get() ));
691 m_pTableSet
->Put( SfxUInt16Item( SID_HTML_MODE
,
692 ::GetHtmlMode( m_pView
->GetDocShell() )));
695 sal_Int32 nCols
= m_xLbTableCol
->n_children();
696 if (nCols
!= m_pRep
->GetAllColCount() && nCols
> 0)
698 // Number of columns has changed: then the TabCols have to be adjusted
699 tools::Long nWidth
= m_pRep
->GetWidth();
701 SwTabCols
aTabCols( nCols
);
702 aTabCols
.SetRight( nWidth
);
703 aTabCols
.SetRightMax( nWidth
);
706 const sal_Int32 nStep
= nWidth
/ (nCols
+1);
707 for( sal_Int32 n
= 0; n
< nCols
; ++n
)
709 aTabCols
.Insert( nStep
*(n
+1), false, n
);
712 m_pRep
.reset(new SwTableRep( aTabCols
));
713 m_pRep
->SetAlign( text::HoriOrientation::NONE
);
714 m_pRep
->SetSpace( nWidth
);
715 m_pRep
->SetWidth( nWidth
);
716 m_pRep
->SetWidthPercent( 100 );
717 m_pTableSet
->Put( SwPtrItem( FN_TABLE_REP
, m_pRep
.get() ));
720 SwAbstractDialogFactory
& rFact
= swui::GetFactory();
722 ScopedVclPtr
<SfxAbstractTabDialog
> pDlg(rFact
.CreateSwTableTabDlg(m_xDialog
.get(), m_pTableSet
.get(), &rSh
));
723 if( RET_OK
== pDlg
->Execute() )
724 m_pTableSet
->Put( *pDlg
->GetOutputItemSet() );
732 IMPL_LINK_NOARG(SwInsertDBColAutoPilot
, AutoFormatHdl
, weld::Button
&, void)
734 SwAbstractDialogFactory
& rFact
= swui::GetFactory();
736 ScopedVclPtr
<AbstractSwAutoFormatDlg
> pDlg(rFact
.CreateSwAutoFormatDlg(m_xDialog
.get(), m_pView
->GetWrtShellPtr(), false, m_xTAutoFormat
.get()));
737 if( RET_OK
== pDlg
->Execute())
738 m_xTAutoFormat
= pDlg
->FillAutoFormatOfIndex();
741 IMPL_LINK(SwInsertDBColAutoPilot
, TVSelectHdl
, weld::TreeView
&, rBox
, void)
743 weld::TreeView
* pGetBox
= &rBox
;
745 SwInsDBColumn
aSrch(pGetBox
->get_selected_text());
746 SwInsDBColumns::const_iterator it
= m_aDBColumns
.find( &aSrch
);
748 // set the selected FieldName at the FormatGroupBox, so that
749 // it's clear what field is configured by the format!
750 OUString
sText( m_xFormatFrame
->get_label().copy( 0, m_nGBFormatLen
));
751 if( aSrch
.sColumn
.isEmpty() )
753 m_xRbDbFormatFromDb
->set_sensitive( false );
754 m_xRbDbFormatFromUsr
->set_sensitive( false );
755 m_xLbDbFormatFromUsr
->set_sensitive( false );
759 bool bEnableFormat
= (*it
)->bHasFormat
;
760 m_xRbDbFormatFromDb
->set_sensitive( bEnableFormat
);
761 m_xRbDbFormatFromUsr
->set_sensitive( bEnableFormat
);
765 sText
+= " (" + aSrch
.sColumn
+ ")";
768 bool bIsDBFormat
= (*it
)->bIsDBFormat
;
769 m_xRbDbFormatFromDb
->set_active( bIsDBFormat
);
770 m_xRbDbFormatFromUsr
->set_active( !bIsDBFormat
);
771 m_xLbDbFormatFromUsr
->set_sensitive( !bIsDBFormat
);
773 m_xLbDbFormatFromUsr
->SetDefFormat( (*it
)->nUsrNumFormat
);
776 m_xFormatFrame
->set_label(sText
);
778 if (m_xLbTableCol
->n_children())
780 // to know later on, what ListBox was the "active", a Flag
781 // is remembered in the 1st entry
782 if (&rBox
== m_xLbTableCol
.get())
783 m_xLbTableCol
->set_id(0, "tablecols");
785 m_xLbTableCol
->set_id(0, OUString());
789 IMPL_LINK_NOARG(SwInsertDBColAutoPilot
, CBSelectHdl
, weld::ComboBox
&, void)
791 weld::TreeView
* pGetBox
= m_xRbAsTable
->get_active()
792 ? ( m_xLbTableCol
->get_id(0).isEmpty()
793 ? m_xLbTableDbColumn
.get()
794 : m_xLbTableCol
.get() )
795 : m_xLbTextDbColumn
.get();
797 SwInsDBColumn
aSrch(pGetBox
->get_selected_text());
798 SwInsDBColumns::const_iterator it
= m_aDBColumns
.find( &aSrch
);
800 if( !aSrch
.sColumn
.isEmpty() )
802 m_xLbDbFormatFromUsr
->CallSelectHdl();
803 (*it
)->nUsrNumFormat
= m_xLbDbFormatFromUsr
->GetFormat();
807 IMPL_LINK_NOARG(SwInsertDBColAutoPilot
, HeaderHdl
, weld::Toggleable
&, void)
809 bool bEnable
= m_xCbTableHeadon
->get_active();
810 m_xRbHeadlColnms
->set_sensitive( bEnable
);
811 m_xRbHeadlEmpty
->set_sensitive( bEnable
);
814 static void lcl_InsTextInArr( std::u16string_view aText
, DB_Columns
& rColArr
)
818 while( std::u16string_view::npos
!= ( nFndPos
= aText
.find( '\x0A', nSttPos
)) )
822 rColArr
.push_back(std::make_unique
<DB_Column
>(OUString(aText
.substr(nSttPos
, nFndPos
-1))));
824 rColArr
.push_back(std::make_unique
<DB_Column
>());
825 nSttPos
= nFndPos
+ 1;
827 if( nSttPos
< aText
.size() )
829 rColArr
.push_back(std::make_unique
<DB_Column
>(OUString(aText
.substr(nSttPos
))));
833 bool SwInsertDBColAutoPilot::SplitTextToColArr( const OUString
& rText
,
837 // create each of the database columns from the text again
838 // and then save in an array
839 // database columns are in <> and must be present in the columns' array:
840 OUString
sText( rText
);
841 sal_Int32 nFndPos
, nEndPos
, nSttPos
= 0;
843 while( -1 != ( nFndPos
= sText
.indexOf( cDBFieldStart
, nSttPos
)))
845 nSttPos
= nFndPos
+ 1;
846 nEndPos
= sText
.indexOf( cDBFieldEnd
, nSttPos
+1 );
849 // Text in <> brackets found: what is it:
850 SwInsDBColumn
aSrch( sText
.copy( nSttPos
, nEndPos
- nSttPos
));
851 SwInsDBColumns::const_iterator it
= m_aDBColumns
.find( &aSrch
);
852 if( it
!= m_aDBColumns
.end() )
854 // that is a valid field
855 // so surely the text "before":
856 const SwInsDBColumn
& rFndCol
= **it
;
862 ::lcl_InsTextInArr( sText
.subView( 0, nSttPos
-1 ), rColArr
);
863 sText
= sText
.copy( nSttPos
-1 );
866 sText
= sText
.copy( rFndCol
.sColumn
.getLength() + 2 );
869 sal_uInt16 nSubType
= 0;
871 if( rFndCol
.bHasFormat
)
873 if( rFndCol
.bIsDBFormat
)
874 nFormat
= static_cast<sal_uInt32
>(rFndCol
.nDBNumFormat
);
877 nFormat
= rFndCol
.nUsrNumFormat
;
878 nSubType
= nsSwExtendedSubType::SUB_OWN_FMT
;
886 SwWrtShell
& rSh
= m_pView
->GetWrtShell();
887 SwDBFieldType
aFieldType( rSh
.GetDoc(), aSrch
.sColumn
,
889 pNew
= new DB_Column( rFndCol
, *new SwDBField(
890 static_cast<SwDBFieldType
*>(rSh
.InsertFieldType( aFieldType
)),
893 pNew
->pField
->SetSubType( nSubType
);
896 pNew
= new DB_Column( rFndCol
, nFormat
);
898 rColArr
.push_back( std::unique_ptr
<DB_Column
>(pNew
) );
903 // don't forget the last text
904 if( !sText
.isEmpty() )
905 ::lcl_InsTextInArr( sText
, rColArr
);
907 return !rColArr
.empty();
910 void SwInsertDBColAutoPilot::DataToDoc( const Sequence
<Any
>& rSelection
,
911 Reference
< XDataSource
> const & xSource
,
912 Reference
< XConnection
> const & xConnection
,
913 Reference
< sdbc::XResultSet
> const & xResultSet_in
)
915 auto xResultSet
= xResultSet_in
;
917 const Any
* pSelection
= rSelection
.hasElements() ? rSelection
.getConstArray() : nullptr;
918 SwWrtShell
& rSh
= m_pView
->GetWrtShell();
920 //with the drag and drop interface no result set is initially available
921 bool bDisposeResultSet
= false;
922 // we don't have a cursor, so we have to create our own RowSet
923 if ( !xResultSet
.is() )
925 xResultSet
= SwDBManager::createCursor(m_aDBData
.sDataSource
,m_aDBData
.sCommand
,m_aDBData
.nCommandType
,xConnection
,m_pView
);
926 bDisposeResultSet
= xResultSet
.is();
929 Reference
< sdbc::XRow
> xRow(xResultSet
, UNO_QUERY
);
933 rSh
.StartAllAction();
934 bool bUndo
= rSh
.DoesUndo();
938 bool bAsTable
= m_xRbAsTable
->get_active();
939 SvNumberFormatter
& rNumFormatr
= *rSh
.GetNumberFormatter();
941 if( rSh
.HasSelection() )
944 std::optional
<SwWait
> oWait
;
946 Reference
< XColumnsSupplier
> xColsSupp( xResultSet
, UNO_QUERY
);
947 Reference
<XNameAccess
> xCols
= xColsSupp
->getColumns();
949 uno::Reference
<sdbcx::XRowLocate
> xRowLocate(xResultSet
, uno::UNO_QUERY_THROW
);
951 do{ // middle checked loop!!
952 if( bAsTable
) // fill in data as table
956 sal_Int32 nCols
= m_xLbTableCol
->n_children();
958 if( m_xCbTableHeadon
->get_active() )
962 nRows
+= rSelection
.getLength();
966 // prepare the array for the selected columns
967 std::vector
<SwInsDBColumn
*> aColFields
;
968 for( sal_Int32 n
= 0; n
< nCols
; ++n
)
970 SwInsDBColumn
aSrch(m_xLbTableCol
->get_text(n
));
971 SwInsDBColumns::const_iterator it
= m_aDBColumns
.find( &aSrch
);
972 if (it
!= m_aDBColumns
.end())
973 aColFields
.push_back(it
->get());
975 OSL_ENSURE( false, "database column not found" );
979 if( static_cast<size_t>(nCols
) != aColFields
.size() )
981 OSL_ENSURE( false, "not all database columns found" );
982 nCols
= static_cast<sal_Int32
>(aColFields
.size());
987 OSL_ENSURE( false, "wrong parameters" );
991 const SwModuleOptions
* pModOpt
= SW_MOD()->GetModuleConfig();
993 bool bHTML
= 0 != (::GetHtmlMode( m_pView
->GetDocShell() ) & HTMLMODE_ON
);
995 pModOpt
->GetInsTableFlags(bHTML
),
996 nRows
, nCols
, (pSelection
? m_xTAutoFormat
.get(): nullptr) );
997 rSh
.MoveTable( GotoPrevTable
, fnTableStart
);
999 if( pSelection
&& m_pTableSet
)
1002 SfxItemSetFixed
<RES_BOXATR_FORMAT
, RES_BOXATR_VALUE
> aTableSet( rSh
.GetAttrPool() );
1003 bool bIsAutoUpdateCells
= rSh
.IsAutoUpdateCells();
1004 rSh
.SetAutoUpdateCells( false );
1006 if( m_xCbTableHeadon
->get_active() )
1008 for( sal_Int32 n
= 0; n
< nCols
; ++n
)
1010 if( m_xRbHeadlColnms
->get_active() )
1012 rSh
.SwEditShell::Insert2( aColFields
[ n
]->sColumn
);
1018 rSh
.SetRowsToRepeat( 0 );
1020 for( sal_Int32 i
= 0 ; ; ++i
)
1022 bool bBreak
= false;
1027 bBreak
= !xRowLocate
->moveToBookmark(pSelection
[i
]);
1030 bBreak
= !xResultSet
->first();
1032 catch (const Exception
&)
1039 for( sal_Int32 n
= 0; n
< nCols
; ++n
)
1041 // at the very first time, NO GoNextCell, because we're
1042 // already in it. Also no GoNextCell after the Insert,
1043 // because an empty line is added at the end.
1047 const SwInsDBColumn
* pEntry
= aColFields
[ n
];
1049 Reference
< XColumn
> xColumn
;
1050 xCols
->getByName(pEntry
->sColumn
) >>= xColumn
;
1051 Reference
< XPropertySet
> xColumnProps( xColumn
, UNO_QUERY
);
1052 sal_Int32 eDataType
= 0;
1053 if( xColumnProps
.is() )
1055 Any aType
= xColumnProps
->getPropertyValue("Type");
1056 aType
>>= eDataType
;
1060 if( pEntry
->bHasFormat
)
1062 SwTableBoxNumFormat
aNumFormat(
1063 pEntry
->bIsDBFormat
? static_cast<sal_uInt32
>(pEntry
->nDBNumFormat
)
1064 : pEntry
->nUsrNumFormat
);
1065 aTableSet
.Put(aNumFormat
);
1068 double fVal
= xColumn
->getDouble();
1069 if( xColumn
->wasNull() )
1070 aTableSet
.ClearItem( RES_BOXATR_VALUE
);
1073 if(rNumFormatr
.GetType(aNumFormat
.GetValue()) & SvNumFormatType::DATE
)
1075 ::Date
aStandard(1,1,1900);
1076 if (rNumFormatr
.GetNullDate() != aStandard
)
1077 fVal
+= (aStandard
- rNumFormatr
.GetNullDate());
1079 aTableSet
.Put( SwTableBoxValue( fVal
));
1083 aTableSet
.ClearItem( RES_BOXATR_VALUE
);
1084 rSh
.SetTableBoxFormulaAttrs( aTableSet
);
1086 //#i60207# don't insert binary data as string - creates a loop
1087 else if( DataType::BINARY
== eDataType
||
1088 DataType::VARBINARY
== eDataType
||
1089 DataType::LONGVARBINARY
== eDataType
||
1090 DataType::SQLNULL
== eDataType
||
1091 DataType::OTHER
== eDataType
||
1092 DataType::OBJECT
== eDataType
||
1093 DataType::DISTINCT
== eDataType
||
1094 DataType::STRUCT
== eDataType
||
1095 DataType::ARRAY
== eDataType
||
1096 DataType::BLOB
== eDataType
||
1097 DataType::CLOB
== eDataType
||
1098 DataType::REF
== eDataType
1105 const OUString sVal
= xColumn
->getString();
1106 if(!xColumn
->wasNull())
1108 rSh
.SwEditShell::Insert2( sVal
);
1112 catch (const Exception
&)
1114 TOOLS_WARN_EXCEPTION("sw", "");
1120 if ( !xResultSet
->next() )
1123 else if( i
+1 >= rSelection
.getLength() )
1127 oWait
.emplace( *m_pView
->GetDocShell(), true );
1130 rSh
.MoveTable( GotoCurrTable
, fnTableStart
);
1131 if( !pSelection
&& ( m_pTableSet
|| m_xTAutoFormat
))
1137 rSh
.SetTableStyle(*m_xTAutoFormat
);
1139 rSh
.SetAutoUpdateCells( bIsAutoUpdateCells
);
1141 else // add data as fields/text
1144 if( SplitTextToColArr( m_xEdDbText
->get_text(), aColArr
, m_xRbAsField
->get_active() ) )
1146 // now for each data set, we can iterate over the array
1149 if( !rSh
.IsSttPara() )
1150 rSh
.SwEditShell::SplitNode();
1151 if( !rSh
.IsEndPara() )
1153 rSh
.SwEditShell::SplitNode();
1154 rSh
.SwCursorShell::Left(1,SwCursorSkipMode::Chars
);
1157 rSh
.DoUndo( false );
1159 SwTextFormatColl
* pColl
= nullptr;
1161 const OUString
sTmplNm(m_xLbDbParaColl
->get_active_text());
1162 if( m_sNoTmpl
!= sTmplNm
)
1164 pColl
= rSh
.FindTextFormatCollByName( sTmplNm
);
1167 const sal_uInt16 nId
= SwStyleNameMapper::GetPoolIdFromUIName(
1168 sTmplNm
, SwGetPoolIdFromName::TxtColl
);
1169 if( USHRT_MAX
!= nId
)
1170 pColl
= rSh
.GetTextCollFromPool( nId
);
1172 pColl
= rSh
.MakeTextFormatColl( sTmplNm
);
1174 rSh
.SetTextFormatColl( pColl
);
1178 // for adding as fields -> insert a "NextField" after
1180 SwDBFormatData aDBFormatData
;
1181 Reference
< XComponentContext
> xContext( ::comphelper::getProcessComponentContext() );
1182 aDBFormatData
.xFormatter
.set(util::NumberFormatter::create(xContext
), UNO_QUERY_THROW
) ;
1184 Reference
<XPropertySet
> xSourceProps(xSource
, UNO_QUERY
);
1185 if(xSourceProps
.is())
1187 Any aFormats
= xSourceProps
->getPropertyValue("NumberFormatsSupplier");
1188 if(aFormats
.hasValue())
1190 Reference
< util::XNumberFormatsSupplier
> xSuppl
;
1191 aFormats
>>= xSuppl
;
1194 Reference
< XPropertySet
> xSettings
= xSuppl
->getNumberFormatSettings();
1195 Any aNull
= xSettings
->getPropertyValue("NullDate");
1196 aNull
>>= aDBFormatData
.aNullDate
;
1197 if(aDBFormatData
.xFormatter
.is())
1198 aDBFormatData
.xFormatter
->attachNumberFormatsSupplier(xSuppl
);
1202 aDBFormatData
.aLocale
= LanguageTag( rSh
.GetCurLang() ).getLocale();
1203 SwDBNextSetField
aNxtDBField( static_cast<SwDBNextSetFieldType
*>(rSh
.
1204 GetFieldType( 0, SwFieldIds::DbNextSet
)),
1207 bool bSetCursor
= true;
1208 const size_t nCols
= aColArr
.size();
1209 ::sw::mark::IMark
* pMark
= nullptr;
1210 for( sal_Int32 i
= 0 ; ; ++i
)
1212 bool bBreak
= false;
1217 bBreak
= !xRowLocate
->moveToBookmark(pSelection
[i
]);
1220 bBreak
= !xResultSet
->first();
1222 catch (const Exception
&)
1230 for( size_t n
= 0; n
< nCols
; ++n
)
1232 DB_Column
* pDBCol
= aColArr
[ n
].get();
1234 switch( pDBCol
->eColType
)
1236 case DB_Column::Type::FILLTEXT
:
1237 sIns
= *pDBCol
->pText
;
1240 case DB_Column::Type::SPLITPARA
:
1242 // when the template is not the same as the follow template,
1243 // the selected has to be set newly
1244 if( pColl
&& &pColl
->GetNextTextFormatColl() != pColl
)
1245 rSh
.SetTextFormatColl( pColl
);
1248 case DB_Column::Type::COL_FIELD
:
1250 std::unique_ptr
<SwDBField
> pField(static_cast<SwDBField
*>(
1251 pDBCol
->pField
->CopyField().release()));
1252 double nValue
= DBL_MAX
;
1254 Reference
< XPropertySet
> xColumnProps
;
1255 xCols
->getByName(pDBCol
->pColInfo
->sColumn
) >>= xColumnProps
;
1257 pField
->SetExpansion( SwDBManager::GetDBField(
1261 if( DBL_MAX
!= nValue
)
1263 Any aType
= xColumnProps
->getPropertyValue("Type");
1264 sal_Int32 eDataType
= 0;
1265 aType
>>= eDataType
;
1266 if( DataType::DATE
== eDataType
|| DataType::TIME
== eDataType
||
1267 DataType::TIMESTAMP
== eDataType
)
1270 ::Date
aStandard(1,1,1900);
1271 ::Date
aCompare(aDBFormatData
.aNullDate
.Day
,
1272 aDBFormatData
.aNullDate
.Month
,
1273 aDBFormatData
.aNullDate
.Year
);
1274 if(aStandard
!= aCompare
)
1275 nValue
+= (aStandard
- aCompare
);
1277 pField
->ChgValue( nValue
, true );
1279 pField
->SetInitialized();
1281 rSh
.InsertField2( *pField
);
1285 case DB_Column::Type::COL_TEXT
:
1287 double nValue
= DBL_MAX
;
1288 Reference
< XPropertySet
> xColumnProps
;
1289 xCols
->getByName(pDBCol
->pColInfo
->sColumn
) >>= xColumnProps
;
1290 sIns
= SwDBManager::GetDBField(
1294 if( pDBCol
->nFormat
&&
1298 if(rNumFormatr
.GetType(pDBCol
->nFormat
) & SvNumFormatType::DATE
)
1300 ::Date
aStandard(1,1,1900);
1301 if (rNumFormatr
.GetNullDate() != aStandard
)
1302 nValue
+= (aStandard
- rNumFormatr
.GetNullDate());
1304 rNumFormatr
.GetOutputString( nValue
,
1312 if( !sIns
.isEmpty() )
1318 // to the beginning and set a mark, so that
1319 // the cursor can be set to the initial position
1322 rSh
.SwCursorShell::MovePara(
1323 GoCurrPara
, fnParaStart
);
1324 pMark
= rSh
.SetBookmark(
1327 IDocumentMarkAccess::MarkType::UNO_BOOKMARK
);
1328 rSh
.SwCursorShell::MovePara(
1329 GoCurrPara
, fnParaEnd
);
1337 bool bNext
= xResultSet
->next();
1341 else if( i
+1 >= rSelection
.getLength() )
1344 if( m_xRbAsField
->get_active() )
1345 rSh
.InsertField2( aNxtDBField
);
1347 if( !rSh
.IsSttPara() )
1348 rSh
.SwEditShell::SplitNode();
1351 oWait
.emplace( *m_pView
->GetDocShell(), true );
1354 if( !bSetCursor
&& pMark
!= nullptr)
1357 rSh
.GotoMark( pMark
);
1358 rSh
.getIDocumentMarkAccess()->deleteMark( pMark
);
1363 // write configuration
1365 }while( false ); // middle checked loop
1370 rSh
.AppendUndoForInsertFromDB( bAsTable
);
1376 if ( bDisposeResultSet
)
1377 ::comphelper::disposeComponent(xResultSet
);
1380 void SwInsertDBColAutoPilot::SetTabSet()
1382 SwWrtShell
& rSh
= m_pView
->GetWrtShell();
1383 const SfxPoolItem
* pItem
;
1387 if (m_xTAutoFormat
->IsFrame())
1389 // border is from AutoFormat
1390 m_pTableSet
->ClearItem( RES_BOX
);
1391 m_pTableSet
->ClearItem( SID_ATTR_BORDER_INNER
);
1393 if (m_xTAutoFormat
->IsBackground())
1395 m_pTableSet
->ClearItem( RES_BACKGROUND
);
1396 m_pTableSet
->ClearItem( SID_ATTR_BRUSH_ROW
);
1397 m_pTableSet
->ClearItem( SID_ATTR_BRUSH_TABLE
);
1402 // remove the defaults again, it makes no sense to set them
1403 SvxBrushItem
aBrush( RES_BACKGROUND
);
1404 static const sal_uInt16 aIds
[3] =
1405 { RES_BACKGROUND
, SID_ATTR_BRUSH_ROW
, SID_ATTR_BRUSH_TABLE
};
1406 for(sal_uInt16 i
: aIds
)
1407 if( SfxItemState::SET
== m_pTableSet
->GetItemState( i
,
1408 false, &pItem
) && *pItem
== aBrush
)
1409 m_pTableSet
->ClearItem( i
);
1412 const SfxStringItem
* pTableNameItem
= m_pTableSet
->GetItemIfSet( FN_PARAM_TABLE_NAME
, false);
1413 if( pTableNameItem
&& pTableNameItem
->GetValue() == rSh
.GetTableFormat()->GetName() )
1414 m_pTableSet
->ClearItem( FN_PARAM_TABLE_NAME
);
1416 rSh
.MoveTable( GotoCurrTable
, fnTableStart
);
1418 rSh
.MoveTable( GotoCurrTable
, fnTableEnd
);
1420 ItemSetToTableParam( *m_pTableSet
, rSh
);
1423 rSh
.MoveTable( GotoCurrTable
, fnTableStart
);
1426 static Sequence
<OUString
> lcl_createSourceNames(std::u16string_view rNodeName
)
1428 Sequence
<OUString
> aSourceNames(11);
1429 OUString
* pNames
= aSourceNames
.getArray();
1430 pNames
[0] = OUString::Concat(rNodeName
) + "/DataSource";
1431 pNames
[1] = OUString::Concat(rNodeName
) + "/Command";
1432 pNames
[2] = OUString::Concat(rNodeName
) + "/CommandType";
1433 pNames
[3] = OUString::Concat(rNodeName
) + "/ColumnsToText";
1434 pNames
[4] = OUString::Concat(rNodeName
) + "/ColumnsToTable";
1435 pNames
[5] = OUString::Concat(rNodeName
) + "/ParaStyle";
1436 pNames
[6] = OUString::Concat(rNodeName
) + "/TableAutoFormat";
1437 pNames
[7] = OUString::Concat(rNodeName
) + "/IsTable";
1438 pNames
[8] = OUString::Concat(rNodeName
) + "/IsField";
1439 pNames
[9] = OUString::Concat(rNodeName
) + "/IsHeadlineOn";
1440 pNames
[10] = OUString::Concat(rNodeName
) + "/IsEmptyHeadline";
1441 return aSourceNames
;
1444 static Sequence
<OUString
> lcl_CreateSubNames(std::u16string_view rSubNodeName
)
1448 OUString::Concat(rSubNodeName
) + "/ColumnName",
1449 OUString::Concat(rSubNodeName
) + "/ColumnIndex",
1450 OUString::Concat(rSubNodeName
) + "/IsNumberFormat",
1451 OUString::Concat(rSubNodeName
) + "/IsNumberFormatFromDataBase",
1452 OUString::Concat(rSubNodeName
) + "/NumberFormat",
1453 OUString::Concat(rSubNodeName
) + "/NumberFormatLocale"
1457 static OUString
lcl_CreateUniqueName(const Sequence
<OUString
>& aNames
)
1459 sal_Int32 nIdx
= aNames
.getLength();
1462 const OUString sRet
= "_" + OUString::number(nIdx
++);
1463 if ( comphelper::findValue(aNames
, sRet
) == -1 )
1464 return sRet
; // No match found, return unique name
1468 void SwInsertDBColAutoPilot::Notify( const css::uno::Sequence
< OUString
>& ) {}
1470 void SwInsertDBColAutoPilot::ImplCommit()
1472 Sequence
<OUString
> aNames
= GetNodeNames(OUString());
1473 //remove entries that contain this data source + table at first
1474 for(OUString
const & nodeName
: std::as_const(aNames
))
1476 Sequence
<Any
> aSourceProperties
= GetProperties({ nodeName
+ "/DataSource", nodeName
+ "/Command" });
1477 const Any
* pSourceProps
= aSourceProperties
.getArray();
1478 OUString sSource
, sCommand
;
1479 pSourceProps
[0] >>= sSource
;
1480 pSourceProps
[1] >>= sCommand
;
1481 if(sSource
==m_aDBData
.sDataSource
&& sCommand
==m_aDBData
.sCommand
)
1483 ClearNodeElements(OUString(), { nodeName
});
1487 aNames
= GetNodeNames(OUString());
1488 OUString sNewNode
= lcl_CreateUniqueName(aNames
);
1489 Sequence
<OUString
> aNodeNames
= lcl_createSourceNames(sNewNode
);
1490 Sequence
<PropertyValue
> aValues(aNodeNames
.getLength());
1491 PropertyValue
* pValues
= aValues
.getArray();
1492 const OUString
* pNodeNames
= aNodeNames
.getConstArray();
1493 for(sal_Int32 i
= 0; i
< aNodeNames
.getLength(); i
++)
1495 pValues
[i
].Name
= "/" + pNodeNames
[i
];
1498 pValues
[0].Value
<<= m_aDBData
.sDataSource
;
1499 pValues
[1].Value
<<= m_aDBData
.sCommand
;
1500 pValues
[2].Value
<<= m_aDBData
.nCommandType
;
1501 pValues
[3].Value
<<= m_xEdDbText
->get_text();
1504 const sal_Int32 nCnt
= m_xLbTableCol
->n_children();
1505 for( sal_Int32 n
= 0; n
< nCnt
; ++n
)
1506 sTmp
+= m_xLbTableCol
->get_text(n
) + "\x0a";
1508 if (!sTmp
.isEmpty())
1509 pValues
[4].Value
<<= sTmp
;
1511 if( m_sNoTmpl
!= (sTmp
= m_xLbDbParaColl
->get_active_text()) )
1512 pValues
[5].Value
<<= sTmp
;
1515 pValues
[6].Value
<<= m_xTAutoFormat
->GetName();
1517 pValues
[7].Value
<<= m_xRbAsTable
->get_active();
1518 pValues
[8].Value
<<= m_xRbAsField
->get_active();
1519 pValues
[9].Value
<<= m_xCbTableHeadon
->get_active();
1520 pValues
[10].Value
<<= m_xRbHeadlEmpty
->get_active();
1522 SetSetProperties(OUString(), aValues
);
1524 sNewNode
+= "/ColumnSet";
1526 LanguageType
ePrevLang(0xffff);
1528 SvNumberFormatter
& rNFormatr
= *m_pView
->GetWrtShell().GetNumberFormatter();
1529 for(size_t nCol
= 0; nCol
< m_aDBColumns
.size(); nCol
++)
1531 SwInsDBColumn
* pColumn
= m_aDBColumns
[nCol
].get();
1532 OUString
sColumnInsertNode(sNewNode
+ "/__");
1534 sColumnInsertNode
+= "00";
1535 else if( nCol
< 100 )
1536 sColumnInsertNode
+= "0";
1537 sColumnInsertNode
+= OUString::number( nCol
);
1539 const Sequence
<OUString
> aSubNodeNames
= lcl_CreateSubNames(sColumnInsertNode
);
1540 Sequence
<PropertyValue
> aSubValues(aSubNodeNames
.getLength());
1541 PropertyValue
* pSubValues
= aSubValues
.getArray();
1544 for( const OUString
& rSubNodeName
: aSubNodeNames
)
1545 pSubValues
[i
++].Name
= rSubNodeName
;
1546 pSubValues
[0].Value
<<= pColumn
->sColumn
;
1547 pSubValues
[1].Value
<<= i
;
1548 pSubValues
[2].Value
<<= pColumn
->bHasFormat
;
1549 pSubValues
[3].Value
<<= pColumn
->bIsDBFormat
;
1551 SwStyleNameMapper::FillUIName( RES_POOLCOLL_STANDARD
, sTmp
);
1552 const SvNumberformat
* pNF
= rNFormatr
.GetEntry( pColumn
->nUsrNumFormat
);
1556 pSubValues
[4].Value
<<= pNF
->GetFormatstring();
1557 eLang
= pNF
->GetLanguage();
1561 pSubValues
[4].Value
<<= sTmp
;
1562 eLang
= GetAppLanguage();
1566 if( eLang
!= ePrevLang
)
1568 sPrevLang
= LanguageTag::convertToBcp47( eLang
);
1572 pSubValues
[5].Value
<<= sPrevLang
;
1573 SetSetProperties(sNewNode
, aSubValues
);
1577 void SwInsertDBColAutoPilot::Load()
1579 const Sequence
<OUString
> aNames
= GetNodeNames(OUString());
1580 SvNumberFormatter
& rNFormatr
= *m_pView
->GetWrtShell().GetNumberFormatter();
1581 for(OUString
const & nodeName
: aNames
)
1583 //search for entries with the appropriate data source and table
1584 Sequence
<OUString
> aSourceNames
= lcl_createSourceNames(nodeName
);
1586 Sequence
< Any
> aDataSourceProps
= GetProperties(aSourceNames
);
1587 const Any
* pDataSourceProps
= aDataSourceProps
.getConstArray();
1588 OUString sSource
, sCommand
;
1589 sal_Int16 nCommandType
;
1590 pDataSourceProps
[0] >>= sSource
;
1591 pDataSourceProps
[1] >>= sCommand
;
1592 pDataSourceProps
[2] >>= nCommandType
;
1593 if(sSource
== m_aDBData
.sDataSource
&& sCommand
== m_aDBData
.sCommand
)
1595 DB_ColumnConfigData aNewData
;
1597 pDataSourceProps
[3] >>= aNewData
.sEdit
;
1598 pDataSourceProps
[4] >>= aNewData
.sTableList
;
1599 pDataSourceProps
[5] >>= aNewData
.sTmplNm
;
1600 pDataSourceProps
[6] >>= aNewData
.sTAutoFormatNm
;
1601 if(pDataSourceProps
[7].hasValue())
1602 aNewData
.bIsTable
= *o3tl::doAccess
<bool>(pDataSourceProps
[7]);
1603 if(pDataSourceProps
[8].hasValue())
1604 aNewData
.bIsField
= *o3tl::doAccess
<bool>(pDataSourceProps
[8]);
1605 if(pDataSourceProps
[9].hasValue())
1606 aNewData
.bIsHeadlineOn
= *o3tl::doAccess
<bool>(pDataSourceProps
[9]);
1607 if(pDataSourceProps
[10].hasValue())
1608 aNewData
.bIsEmptyHeadln
= *o3tl::doAccess
<bool>(pDataSourceProps
[10]);
1610 const OUString
sSubNodeName(nodeName
+ "/ColumnSet/");
1611 const Sequence
<OUString
> aSubNames
= GetNodeNames(sSubNodeName
);
1612 for(const OUString
& rSubName
: aSubNames
)
1614 Sequence
<OUString
> aSubNodeNames
=
1615 lcl_CreateSubNames(Concat2View(sSubNodeName
+ rSubName
));
1616 Sequence
< Any
> aSubProps
= GetProperties(aSubNodeNames
);
1617 const Any
* pSubProps
= aSubProps
.getConstArray();
1620 pSubProps
[0] >>= sColumn
;
1621 // check for existence of the loaded column name
1622 bool bFound
= false;
1623 for(size_t nRealColumn
= 0; nRealColumn
< m_aDBColumns
.size(); ++nRealColumn
)
1625 if(m_aDBColumns
[nRealColumn
]->sColumn
== sColumn
)
1633 sal_Int16 nIndex
= 0;
1634 pSubProps
[1] >>= nIndex
;
1635 std::unique_ptr
<SwInsDBColumn
> pInsDBColumn(new SwInsDBColumn(sColumn
));
1636 if(pSubProps
[2].hasValue())
1637 pInsDBColumn
->bHasFormat
= *o3tl::doAccess
<bool>(pSubProps
[2]);
1638 if(pSubProps
[3].hasValue())
1639 pInsDBColumn
->bIsDBFormat
= *o3tl::doAccess
<bool>(pSubProps
[3]);
1641 pSubProps
[4] >>= pInsDBColumn
->sUsrNumFormat
;
1642 OUString sNumberFormatLocale
;
1643 pSubProps
[5] >>= sNumberFormatLocale
;
1645 /* XXX Earlier versions wrote a Country-Language string in
1646 * SwInsertDBColAutoPilot::Commit() that here was read as
1647 * Language-Country with 2 characters copied to language,
1648 * 1 character separator and unconditionally 2 characters read
1649 * as country. So for 'DE-de' and locales that have similar
1650 * case-insensitive equal language/country combos that may have
1651 * worked, for all others not. FIXME if you need to read old
1652 * data that you were never able to read before. */
1653 pInsDBColumn
->eUsrNumFormatLng
= LanguageTag::convertToLanguageType( sNumberFormatLocale
);
1655 pInsDBColumn
->nUsrNumFormat
= rNFormatr
.GetEntryKey( pInsDBColumn
->sUsrNumFormat
,
1656 pInsDBColumn
->eUsrNumFormatLng
);
1658 aNewData
.aDBColumns
.insert(std::move(pInsDBColumn
));
1660 OUString
sTmp( aNewData
.sTableList
);
1661 if( !sTmp
.isEmpty() )
1665 const OUString
sEntry( sTmp
.getToken( 0, '\x0a', n
) );
1666 //preselect column - if they still exist!
1667 if (m_xLbTableDbColumn
->find_text(sEntry
) != -1)
1669 m_xLbTableCol
->append_text(sEntry
);
1670 m_xLbTableDbColumn
->remove_text(sEntry
);
1674 if (!m_xLbTableDbColumn
->n_children())
1676 m_xIbDbcolAllTo
->set_sensitive( false );
1677 m_xIbDbcolOneTo
->set_sensitive( false );
1679 m_xIbDbcolOneFrom
->set_sensitive(true);
1680 m_xIbDbcolAllFrom
->set_sensitive(true);
1682 m_xEdDbText
->set_text( aNewData
.sEdit
);
1684 sTmp
= aNewData
.sTmplNm
;
1685 if( !sTmp
.isEmpty() )
1686 m_xLbDbParaColl
->set_active_text(sTmp
);
1688 m_xLbDbParaColl
->set_active(0);
1690 m_xTAutoFormat
.reset();
1691 sTmp
= aNewData
.sTAutoFormatNm
;
1692 if( !sTmp
.isEmpty() )
1694 // then load the AutoFormat file and look for Autoformat first
1695 SwTableAutoFormatTable aAutoFormatTable
;
1696 aAutoFormatTable
.Load();
1697 for( size_t nAutoFormat
= aAutoFormatTable
.size(); nAutoFormat
; )
1698 if( sTmp
== aAutoFormatTable
[ --nAutoFormat
].GetName() )
1700 m_xTAutoFormat
.reset(new SwTableAutoFormat(aAutoFormatTable
[nAutoFormat
]));
1705 m_xRbAsTable
->set_active( aNewData
.bIsTable
);
1706 m_xRbAsField
->set_active( aNewData
.bIsField
);
1707 m_xRbAsText
->set_active( !aNewData
.bIsTable
&& !aNewData
.bIsField
);
1709 m_xCbTableHeadon
->set_active( aNewData
.bIsHeadlineOn
);
1710 m_xRbHeadlColnms
->set_active( !aNewData
.bIsEmptyHeadln
);
1711 m_xRbHeadlEmpty
->set_active( aNewData
.bIsEmptyHeadln
);
1712 HeaderHdl(*m_xCbTableHeadon
);
1714 // now copy the user defined Numberformat strings to the
1715 // Shell. Then only these are available as ID
1716 for( size_t n
= 0; n
< m_aDBColumns
.size() ; ++n
)
1718 SwInsDBColumn
& rSet
= *m_aDBColumns
[ n
];
1719 for( size_t m
= 0; m
< aNewData
.aDBColumns
.size() ; ++m
)
1721 SwInsDBColumn
& rGet
= *aNewData
.aDBColumns
[ m
];
1722 if(rGet
.sColumn
== rSet
.sColumn
)
1724 if( rGet
.bHasFormat
&& !rGet
.bIsDBFormat
)
1726 rSet
.bIsDBFormat
= false;
1727 rSet
.nUsrNumFormat
= rNFormatr
.GetEntryKey( rGet
.sUsrNumFormat
,
1728 rGet
.eUsrNumFormatLng
);
1729 if( NUMBERFORMAT_ENTRY_NOT_FOUND
== rSet
.nUsrNumFormat
)
1731 sal_Int32 nCheckPos
;
1732 SvNumFormatType nType
;
1733 rNFormatr
.PutEntry( rGet
.sUsrNumFormat
, nCheckPos
, nType
,
1734 rSet
.nUsrNumFormat
, rGet
.eUsrNumFormatLng
);
1742 // when the cursor is inside of a table, table must NEVER be selectable
1743 if( !m_xRbAsTable
->get_sensitive() && m_xRbAsTable
->get_active() )
1744 m_xRbAsField
->set_active(true);
1750 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */