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(), u
"modules/swriter/ui/insertdbcolumnsdialog.ui"_ustr
, u
"InsertDbColumnsDialog"_ustr
)
178 , ConfigItem(u
"Office.Writer/InsertData/DataSet"_ustr
, ConfigItemMode::NONE
)
179 , m_aDBData(std::move(aData
))
180 , m_sNoTmpl(SwResId(SW_STR_NONE
))
182 , m_xRbAsTable(m_xBuilder
->weld_radio_button(u
"astable"_ustr
))
183 , m_xRbAsField(m_xBuilder
->weld_radio_button(u
"asfields"_ustr
))
184 , m_xRbAsText(m_xBuilder
->weld_radio_button(u
"astext"_ustr
))
185 , m_xHeadFrame(m_xBuilder
->weld_frame(u
"dbframe"_ustr
))
186 , m_xLbTableDbColumn(m_xBuilder
->weld_tree_view(u
"tabledbcols"_ustr
))
187 , m_xLbTextDbColumn(m_xBuilder
->weld_tree_view(u
"tabletxtcols"_ustr
))
188 , m_xFormatFrame(m_xBuilder
->weld_frame(u
"formatframe"_ustr
))
189 , m_xRbDbFormatFromDb(m_xBuilder
->weld_radio_button(u
"fromdatabase"_ustr
))
190 , m_xRbDbFormatFromUsr(m_xBuilder
->weld_radio_button(u
"userdefined"_ustr
))
191 , m_xLbDbFormatFromUsr(new NumFormatListBox(m_xBuilder
->weld_combo_box(u
"numformat"_ustr
)))
192 , m_xIbDbcolToEdit(m_xBuilder
->weld_button(u
"toedit"_ustr
))
193 , m_xEdDbText(m_xBuilder
->weld_text_view(u
"textview"_ustr
))
194 , m_xFtDbParaColl(m_xBuilder
->weld_label(u
"parastylelabel"_ustr
))
195 , m_xLbDbParaColl(m_xBuilder
->weld_combo_box(u
"parastyle"_ustr
))
196 , m_xIbDbcolAllTo(m_xBuilder
->weld_button(u
"oneright"_ustr
))
197 , m_xIbDbcolOneTo(m_xBuilder
->weld_button(u
"allright"_ustr
))
198 , m_xIbDbcolOneFrom(m_xBuilder
->weld_button(u
"oneleft"_ustr
))
199 , m_xIbDbcolAllFrom(m_xBuilder
->weld_button(u
"allleft"_ustr
))
200 , m_xFtTableCol(m_xBuilder
->weld_label(u
"tablecolft"_ustr
))
201 , m_xLbTableCol(m_xBuilder
->weld_tree_view(u
"tablecols"_ustr
))
202 , m_xCbTableHeadon(m_xBuilder
->weld_check_button(u
"tableheading"_ustr
))
203 , m_xRbHeadlColnms(m_xBuilder
->weld_radio_button(u
"columnname"_ustr
))
204 , m_xRbHeadlEmpty(m_xBuilder
->weld_radio_button(u
"rowonly"_ustr
))
205 , m_xPbTableFormat(m_xBuilder
->weld_button(u
"tableformat"_ustr
))
206 , m_xPbTableAutofmt(m_xBuilder
->weld_button(u
"autoformat"_ustr
))
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(u
"NumberFormatsSupplier"_ustr
);
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(u
"Type"_ustr
);
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(u
"FormatKey"_ustr
);
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(u
"FormatString"_ustr
);
276 Any aLocale
= xNumProps
->getPropertyValue(u
"Locale"_ustr
);
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_selection_changed(LINK(this, SwInsertDBColAutoPilot
, TVSelectHdl
));
362 m_xLbTableDbColumn
->connect_selection_changed(LINK(this, SwInsertDBColAutoPilot
, TVSelectHdl
));
363 m_xLbDbFormatFromUsr
->connect_changed( LINK( this, SwInsertDBColAutoPilot
, CBSelectHdl
));
364 m_xLbTableCol
->connect_selection_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 VclPtr
<SfxAbstractTabDialog
> pDlg(rFact
.CreateSwTableTabDlg(m_xDialog
.get(), m_pTableSet
.get(), &rSh
));
723 pDlg
->StartExecuteAsync(
724 [this, pDlg
, bNewSet
] (sal_Int32 nResult
)->void
726 if( nResult
== RET_OK
)
727 m_pTableSet
->Put( *pDlg
->GetOutputItemSet() );
738 IMPL_LINK_NOARG(SwInsertDBColAutoPilot
, AutoFormatHdl
, weld::Button
&, void)
740 SwAbstractDialogFactory
& rFact
= swui::GetFactory();
742 VclPtr
<AbstractSwAutoFormatDlg
> pDlg(rFact
.CreateSwAutoFormatDlg(m_xDialog
.get(), m_pView
->GetWrtShellPtr(), false, m_xTAutoFormat
.get()));
743 pDlg
->StartExecuteAsync(
744 [this, pDlg
] (sal_Int32 nResult
)->void
746 if (nResult
== RET_OK
)
749 m_xTAutoFormat
= pDlg
->FillAutoFormatOfIndex();
756 IMPL_LINK(SwInsertDBColAutoPilot
, TVSelectHdl
, weld::TreeView
&, rBox
, void)
758 weld::TreeView
* pGetBox
= &rBox
;
760 SwInsDBColumn
aSrch(pGetBox
->get_selected_text());
761 SwInsDBColumns::const_iterator it
= m_aDBColumns
.find( &aSrch
);
763 // set the selected FieldName at the FormatGroupBox, so that
764 // it's clear what field is configured by the format!
765 OUString
sText( m_xFormatFrame
->get_label().copy( 0, m_nGBFormatLen
));
766 if( aSrch
.sColumn
.isEmpty() )
768 m_xRbDbFormatFromDb
->set_sensitive( false );
769 m_xRbDbFormatFromUsr
->set_sensitive( false );
770 m_xLbDbFormatFromUsr
->set_sensitive( false );
774 bool bEnableFormat
= (*it
)->bHasFormat
;
775 m_xRbDbFormatFromDb
->set_sensitive( bEnableFormat
);
776 m_xRbDbFormatFromUsr
->set_sensitive( bEnableFormat
);
780 sText
+= " (" + aSrch
.sColumn
+ ")";
783 bool bIsDBFormat
= (*it
)->bIsDBFormat
;
784 m_xRbDbFormatFromDb
->set_active( bIsDBFormat
);
785 m_xRbDbFormatFromUsr
->set_active( !bIsDBFormat
);
786 m_xLbDbFormatFromUsr
->set_sensitive( !bIsDBFormat
);
788 m_xLbDbFormatFromUsr
->SetDefFormat( (*it
)->nUsrNumFormat
);
791 m_xFormatFrame
->set_label(sText
);
793 if (m_xLbTableCol
->n_children())
795 // to know later on, what ListBox was the "active", a Flag
796 // is remembered in the 1st entry
797 if (&rBox
== m_xLbTableCol
.get())
798 m_xLbTableCol
->set_id(0, u
"tablecols"_ustr
);
800 m_xLbTableCol
->set_id(0, OUString());
804 IMPL_LINK_NOARG(SwInsertDBColAutoPilot
, CBSelectHdl
, weld::ComboBox
&, void)
806 weld::TreeView
* pGetBox
= m_xRbAsTable
->get_active()
807 ? ( m_xLbTableCol
->get_id(0).isEmpty()
808 ? m_xLbTableDbColumn
.get()
809 : m_xLbTableCol
.get() )
810 : m_xLbTextDbColumn
.get();
812 SwInsDBColumn
aSrch(pGetBox
->get_selected_text());
813 SwInsDBColumns::const_iterator it
= m_aDBColumns
.find( &aSrch
);
815 if( !aSrch
.sColumn
.isEmpty() )
817 m_xLbDbFormatFromUsr
->CallSelectHdl();
818 (*it
)->nUsrNumFormat
= m_xLbDbFormatFromUsr
->GetFormat();
822 IMPL_LINK_NOARG(SwInsertDBColAutoPilot
, HeaderHdl
, weld::Toggleable
&, void)
824 bool bEnable
= m_xCbTableHeadon
->get_active();
825 m_xRbHeadlColnms
->set_sensitive( bEnable
);
826 m_xRbHeadlEmpty
->set_sensitive( bEnable
);
829 static void lcl_InsTextInArr( std::u16string_view aText
, DB_Columns
& rColArr
)
833 while( std::u16string_view::npos
!= ( nFndPos
= aText
.find( '\x0A', nSttPos
)) )
837 rColArr
.push_back(std::make_unique
<DB_Column
>(OUString(aText
.substr(nSttPos
, nFndPos
-1))));
839 rColArr
.push_back(std::make_unique
<DB_Column
>());
840 nSttPos
= nFndPos
+ 1;
842 if( nSttPos
< aText
.size() )
844 rColArr
.push_back(std::make_unique
<DB_Column
>(OUString(aText
.substr(nSttPos
))));
848 bool SwInsertDBColAutoPilot::SplitTextToColArr( const OUString
& rText
,
852 // create each of the database columns from the text again
853 // and then save in an array
854 // database columns are in <> and must be present in the columns' array:
855 OUString
sText( rText
);
856 sal_Int32 nFndPos
, nEndPos
, nSttPos
= 0;
858 while( -1 != ( nFndPos
= sText
.indexOf( cDBFieldStart
, nSttPos
)))
860 nSttPos
= nFndPos
+ 1;
861 nEndPos
= sText
.indexOf( cDBFieldEnd
, nSttPos
+1 );
864 // Text in <> brackets found: what is it:
865 SwInsDBColumn
aSrch( sText
.copy( nSttPos
, nEndPos
- nSttPos
));
866 SwInsDBColumns::const_iterator it
= m_aDBColumns
.find( &aSrch
);
867 if( it
!= m_aDBColumns
.end() )
869 // that is a valid field
870 // so surely the text "before":
871 const SwInsDBColumn
& rFndCol
= **it
;
877 ::lcl_InsTextInArr( sText
.subView( 0, nSttPos
-1 ), rColArr
);
878 sText
= sText
.copy( nSttPos
-1 );
881 sText
= sText
.copy( rFndCol
.sColumn
.getLength() + 2 );
884 sal_uInt16 nSubType
= 0;
886 if( rFndCol
.bHasFormat
)
888 if( rFndCol
.bIsDBFormat
)
889 nFormat
= static_cast<sal_uInt32
>(rFndCol
.nDBNumFormat
);
892 nFormat
= rFndCol
.nUsrNumFormat
;
893 nSubType
= nsSwExtendedSubType::SUB_OWN_FMT
;
901 SwWrtShell
& rSh
= m_pView
->GetWrtShell();
902 SwDBFieldType
aFieldType( rSh
.GetDoc(), aSrch
.sColumn
,
904 pNew
= new DB_Column( rFndCol
, *new SwDBField(
905 static_cast<SwDBFieldType
*>(rSh
.InsertFieldType( aFieldType
)),
908 pNew
->pField
->SetSubType( nSubType
);
911 pNew
= new DB_Column( rFndCol
, nFormat
);
913 rColArr
.push_back( std::unique_ptr
<DB_Column
>(pNew
) );
918 // don't forget the last text
919 if( !sText
.isEmpty() )
920 ::lcl_InsTextInArr( sText
, rColArr
);
922 return !rColArr
.empty();
925 void SwInsertDBColAutoPilot::DataToDoc( const Sequence
<Any
>& rSelection
,
926 Reference
< XDataSource
> const & xSource
,
927 Reference
< XConnection
> const & xConnection
,
928 Reference
< sdbc::XResultSet
> const & xResultSet_in
)
930 auto xResultSet
= xResultSet_in
;
932 const Any
* pSelection
= rSelection
.hasElements() ? rSelection
.getConstArray() : nullptr;
933 SwWrtShell
& rSh
= m_pView
->GetWrtShell();
935 //with the drag and drop interface no result set is initially available
936 bool bDisposeResultSet
= false;
937 // we don't have a cursor, so we have to create our own RowSet
938 if ( !xResultSet
.is() )
940 xResultSet
= SwDBManager::createCursor(m_aDBData
.sDataSource
,m_aDBData
.sCommand
,m_aDBData
.nCommandType
,xConnection
,m_pView
);
941 bDisposeResultSet
= xResultSet
.is();
944 Reference
< sdbc::XRow
> xRow(xResultSet
, UNO_QUERY
);
948 rSh
.StartAllAction();
949 bool bUndo
= rSh
.DoesUndo();
953 bool bAsTable
= m_xRbAsTable
->get_active();
954 SvNumberFormatter
& rNumFormatr
= *rSh
.GetNumberFormatter();
956 if( rSh
.HasSelection() )
959 std::optional
<SwWait
> oWait
;
961 Reference
< XColumnsSupplier
> xColsSupp( xResultSet
, UNO_QUERY
);
962 Reference
<XNameAccess
> xCols
= xColsSupp
->getColumns();
964 uno::Reference
<sdbcx::XRowLocate
> xRowLocate(xResultSet
, uno::UNO_QUERY_THROW
);
966 do{ // middle checked loop!!
967 if( bAsTable
) // fill in data as table
971 sal_Int32 nCols
= m_xLbTableCol
->n_children();
973 if( m_xCbTableHeadon
->get_active() )
977 nRows
+= rSelection
.getLength();
981 // prepare the array for the selected columns
982 std::vector
<SwInsDBColumn
*> aColFields
;
983 for( sal_Int32 n
= 0; n
< nCols
; ++n
)
985 SwInsDBColumn
aSrch(m_xLbTableCol
->get_text(n
));
986 SwInsDBColumns::const_iterator it
= m_aDBColumns
.find( &aSrch
);
987 if (it
!= m_aDBColumns
.end())
988 aColFields
.push_back(it
->get());
990 OSL_ENSURE( false, "database column not found" );
994 if( static_cast<size_t>(nCols
) != aColFields
.size() )
996 OSL_ENSURE( false, "not all database columns found" );
997 nCols
= static_cast<sal_Int32
>(aColFields
.size());
1000 if(!nRows
|| !nCols
)
1002 OSL_ENSURE( false, "wrong parameters" );
1006 const SwModuleOptions
* pModOpt
= SwModule::get()->GetModuleConfig();
1008 bool bHTML
= 0 != (::GetHtmlMode( m_pView
->GetDocShell() ) & HTMLMODE_ON
);
1010 pModOpt
->GetInsTableFlags(bHTML
),
1011 nRows
, nCols
, (pSelection
? m_xTAutoFormat
.get(): nullptr) );
1012 rSh
.MoveTable( GotoPrevTable
, fnTableStart
);
1014 if( pSelection
&& m_pTableSet
)
1017 SfxItemSetFixed
<RES_BOXATR_FORMAT
, RES_BOXATR_VALUE
> aTableSet( rSh
.GetAttrPool() );
1018 bool bIsAutoUpdateCells
= rSh
.IsAutoUpdateCells();
1019 rSh
.SetAutoUpdateCells( false );
1021 if( m_xCbTableHeadon
->get_active() )
1023 for( sal_Int32 n
= 0; n
< nCols
; ++n
)
1025 if( m_xRbHeadlColnms
->get_active() )
1027 rSh
.SwEditShell::Insert2( aColFields
[ n
]->sColumn
);
1033 rSh
.SetRowsToRepeat( 0 );
1035 for( sal_Int32 i
= 0 ; ; ++i
)
1037 bool bBreak
= false;
1042 bBreak
= !xRowLocate
->moveToBookmark(pSelection
[i
]);
1045 bBreak
= !xResultSet
->first();
1047 catch (const Exception
&)
1054 for( sal_Int32 n
= 0; n
< nCols
; ++n
)
1056 // at the very first time, NO GoNextCell, because we're
1057 // already in it. Also no GoNextCell after the Insert,
1058 // because an empty line is added at the end.
1062 const SwInsDBColumn
* pEntry
= aColFields
[ n
];
1064 Reference
< XColumn
> xColumn
;
1065 xCols
->getByName(pEntry
->sColumn
) >>= xColumn
;
1066 Reference
< XPropertySet
> xColumnProps( xColumn
, UNO_QUERY
);
1067 sal_Int32 eDataType
= 0;
1068 if( xColumnProps
.is() )
1070 Any aType
= xColumnProps
->getPropertyValue(u
"Type"_ustr
);
1071 aType
>>= eDataType
;
1075 if( pEntry
->bHasFormat
)
1077 SwTableBoxNumFormat
aNumFormat(
1078 pEntry
->bIsDBFormat
? static_cast<sal_uInt32
>(pEntry
->nDBNumFormat
)
1079 : pEntry
->nUsrNumFormat
);
1080 aTableSet
.Put(aNumFormat
);
1083 double fVal
= xColumn
->getDouble();
1084 if( xColumn
->wasNull() )
1085 aTableSet
.ClearItem( RES_BOXATR_VALUE
);
1088 if(rNumFormatr
.GetType(aNumFormat
.GetValue()) & SvNumFormatType::DATE
)
1090 ::Date
aStandard(1,1,1900);
1091 if (rNumFormatr
.GetNullDate() != aStandard
)
1092 fVal
+= (aStandard
- rNumFormatr
.GetNullDate());
1094 aTableSet
.Put( SwTableBoxValue( fVal
));
1098 aTableSet
.ClearItem( RES_BOXATR_VALUE
);
1099 rSh
.SetTableBoxFormulaAttrs( aTableSet
);
1101 //#i60207# don't insert binary data as string - creates a loop
1102 else if( DataType::BINARY
== eDataType
||
1103 DataType::VARBINARY
== eDataType
||
1104 DataType::LONGVARBINARY
== eDataType
||
1105 DataType::SQLNULL
== eDataType
||
1106 DataType::OTHER
== eDataType
||
1107 DataType::OBJECT
== eDataType
||
1108 DataType::DISTINCT
== eDataType
||
1109 DataType::STRUCT
== eDataType
||
1110 DataType::ARRAY
== eDataType
||
1111 DataType::BLOB
== eDataType
||
1112 DataType::CLOB
== eDataType
||
1113 DataType::REF
== eDataType
1120 const OUString sVal
= xColumn
->getString();
1121 if(!xColumn
->wasNull())
1123 rSh
.SwEditShell::Insert2( sVal
);
1127 catch (const Exception
&)
1129 TOOLS_WARN_EXCEPTION("sw", "");
1135 if ( !xResultSet
->next() )
1138 else if( i
+1 >= rSelection
.getLength() )
1142 oWait
.emplace( *m_pView
->GetDocShell(), true );
1145 rSh
.MoveTable( GotoCurrTable
, fnTableStart
);
1146 if( !pSelection
&& ( m_pTableSet
|| m_xTAutoFormat
))
1152 rSh
.SetTableStyle(*m_xTAutoFormat
);
1154 rSh
.SetAutoUpdateCells( bIsAutoUpdateCells
);
1156 else // add data as fields/text
1159 if( SplitTextToColArr( m_xEdDbText
->get_text(), aColArr
, m_xRbAsField
->get_active() ) )
1161 // now for each data set, we can iterate over the array
1164 if( !rSh
.IsSttPara() )
1165 rSh
.SwEditShell::SplitNode();
1166 if( !rSh
.IsEndPara() )
1168 rSh
.SwEditShell::SplitNode();
1169 rSh
.SwCursorShell::Left(1,SwCursorSkipMode::Chars
);
1172 rSh
.DoUndo( false );
1174 SwTextFormatColl
* pColl
= nullptr;
1176 const OUString
sTmplNm(m_xLbDbParaColl
->get_active_text());
1177 if( m_sNoTmpl
!= sTmplNm
)
1179 pColl
= rSh
.FindTextFormatCollByName( sTmplNm
);
1182 const sal_uInt16 nId
= SwStyleNameMapper::GetPoolIdFromUIName(
1183 sTmplNm
, SwGetPoolIdFromName::TxtColl
);
1184 if( USHRT_MAX
!= nId
)
1185 pColl
= rSh
.GetTextCollFromPool( nId
);
1187 pColl
= rSh
.MakeTextFormatColl( sTmplNm
);
1189 rSh
.SetTextFormatColl( pColl
);
1193 // for adding as fields -> insert a "NextField" after
1195 SwDBFormatData aDBFormatData
;
1196 const Reference
< XComponentContext
>& xContext( ::comphelper::getProcessComponentContext() );
1197 aDBFormatData
.xFormatter
.set(util::NumberFormatter::create(xContext
), UNO_QUERY_THROW
) ;
1199 Reference
<XPropertySet
> xSourceProps(xSource
, UNO_QUERY
);
1200 if(xSourceProps
.is())
1202 Any aFormats
= xSourceProps
->getPropertyValue(u
"NumberFormatsSupplier"_ustr
);
1203 if(aFormats
.hasValue())
1205 Reference
< util::XNumberFormatsSupplier
> xSuppl
;
1206 aFormats
>>= xSuppl
;
1209 Reference
< XPropertySet
> xSettings
= xSuppl
->getNumberFormatSettings();
1210 Any aNull
= xSettings
->getPropertyValue(u
"NullDate"_ustr
);
1211 aNull
>>= aDBFormatData
.aNullDate
;
1212 if(aDBFormatData
.xFormatter
.is())
1213 aDBFormatData
.xFormatter
->attachNumberFormatsSupplier(xSuppl
);
1217 aDBFormatData
.aLocale
= LanguageTag( rSh
.GetCurLang() ).getLocale();
1218 SwDBNextSetField
aNxtDBField( static_cast<SwDBNextSetFieldType
*>(rSh
.
1219 GetFieldType( 0, SwFieldIds::DbNextSet
)),
1220 u
"1"_ustr
, m_aDBData
);
1222 bool bSetCursor
= true;
1223 const size_t nCols
= aColArr
.size();
1224 ::sw::mark::MarkBase
* pMark
= nullptr;
1225 for( sal_Int32 i
= 0 ; ; ++i
)
1227 bool bBreak
= false;
1232 bBreak
= !xRowLocate
->moveToBookmark(pSelection
[i
]);
1235 bBreak
= !xResultSet
->first();
1237 catch (const Exception
&)
1245 for( size_t n
= 0; n
< nCols
; ++n
)
1247 DB_Column
* pDBCol
= aColArr
[ n
].get();
1249 switch( pDBCol
->eColType
)
1251 case DB_Column::Type::FILLTEXT
:
1252 sIns
= *pDBCol
->pText
;
1255 case DB_Column::Type::SPLITPARA
:
1257 // when the template is not the same as the follow template,
1258 // the selected has to be set newly
1259 if( pColl
&& &pColl
->GetNextTextFormatColl() != pColl
)
1260 rSh
.SetTextFormatColl( pColl
);
1263 case DB_Column::Type::COL_FIELD
:
1265 std::unique_ptr
<SwDBField
> pField(static_cast<SwDBField
*>(
1266 pDBCol
->pField
->CopyField().release()));
1267 double nValue
= DBL_MAX
;
1269 Reference
< XPropertySet
> xColumnProps
;
1270 xCols
->getByName(pDBCol
->pColInfo
->sColumn
) >>= xColumnProps
;
1272 pField
->SetExpansion( SwDBManager::GetDBField(
1276 if( DBL_MAX
!= nValue
)
1278 Any aType
= xColumnProps
->getPropertyValue(u
"Type"_ustr
);
1279 sal_Int32 eDataType
= 0;
1280 aType
>>= eDataType
;
1281 if( DataType::DATE
== eDataType
|| DataType::TIME
== eDataType
||
1282 DataType::TIMESTAMP
== eDataType
)
1285 ::Date
aStandard(1,1,1900);
1286 ::Date
aCompare(aDBFormatData
.aNullDate
.Day
,
1287 aDBFormatData
.aNullDate
.Month
,
1288 aDBFormatData
.aNullDate
.Year
);
1289 if(aStandard
!= aCompare
)
1290 nValue
+= (aStandard
- aCompare
);
1292 pField
->ChgValue( nValue
, true );
1294 pField
->SetInitialized();
1296 rSh
.InsertField2( *pField
);
1300 case DB_Column::Type::COL_TEXT
:
1302 double nValue
= DBL_MAX
;
1303 Reference
< XPropertySet
> xColumnProps
;
1304 xCols
->getByName(pDBCol
->pColInfo
->sColumn
) >>= xColumnProps
;
1305 sIns
= SwDBManager::GetDBField(
1309 if( pDBCol
->nFormat
&&
1313 if(rNumFormatr
.GetType(pDBCol
->nFormat
) & SvNumFormatType::DATE
)
1315 ::Date
aStandard(1,1,1900);
1316 if (rNumFormatr
.GetNullDate() != aStandard
)
1317 nValue
+= (aStandard
- rNumFormatr
.GetNullDate());
1319 rNumFormatr
.GetOutputString( nValue
,
1327 if( !sIns
.isEmpty() )
1333 // to the beginning and set a mark, so that
1334 // the cursor can be set to the initial position
1337 rSh
.SwCursorShell::MovePara(
1338 GoCurrPara
, fnParaStart
);
1339 pMark
= rSh
.SetBookmark(
1342 IDocumentMarkAccess::MarkType::UNO_BOOKMARK
);
1343 rSh
.SwCursorShell::MovePara(
1344 GoCurrPara
, fnParaEnd
);
1352 bool bNext
= xResultSet
->next();
1356 else if( i
+1 >= rSelection
.getLength() )
1359 if( m_xRbAsField
->get_active() )
1360 rSh
.InsertField2( aNxtDBField
);
1362 if( !rSh
.IsSttPara() )
1363 rSh
.SwEditShell::SplitNode();
1366 oWait
.emplace( *m_pView
->GetDocShell(), true );
1369 if( !bSetCursor
&& pMark
!= nullptr)
1372 rSh
.GotoMark( pMark
);
1373 rSh
.getIDocumentMarkAccess()->deleteMark( pMark
);
1378 // write configuration
1380 }while( false ); // middle checked loop
1385 rSh
.AppendUndoForInsertFromDB( bAsTable
);
1391 if ( bDisposeResultSet
)
1392 ::comphelper::disposeComponent(xResultSet
);
1395 void SwInsertDBColAutoPilot::SetTabSet()
1397 SwWrtShell
& rSh
= m_pView
->GetWrtShell();
1398 const SfxPoolItem
* pItem
;
1402 if (m_xTAutoFormat
->IsFrame())
1404 // border is from AutoFormat
1405 m_pTableSet
->ClearItem( RES_BOX
);
1406 m_pTableSet
->ClearItem( SID_ATTR_BORDER_INNER
);
1408 if (m_xTAutoFormat
->IsBackground())
1410 m_pTableSet
->ClearItem( RES_BACKGROUND
);
1411 m_pTableSet
->ClearItem( SID_ATTR_BRUSH_ROW
);
1412 m_pTableSet
->ClearItem( SID_ATTR_BRUSH_TABLE
);
1417 // remove the defaults again, it makes no sense to set them
1418 SvxBrushItem
aBrush( RES_BACKGROUND
);
1419 static const sal_uInt16 aIds
[3] =
1420 { RES_BACKGROUND
, SID_ATTR_BRUSH_ROW
, SID_ATTR_BRUSH_TABLE
};
1421 for(sal_uInt16 i
: aIds
)
1422 if( SfxItemState::SET
== m_pTableSet
->GetItemState( i
,
1423 false, &pItem
) && *pItem
== aBrush
)
1424 m_pTableSet
->ClearItem( i
);
1427 const SfxStringItem
* pTableNameItem
= m_pTableSet
->GetItemIfSet( FN_PARAM_TABLE_NAME
, false);
1428 if( pTableNameItem
&& pTableNameItem
->GetValue() == rSh
.GetTableFormat()->GetName() )
1429 m_pTableSet
->ClearItem( FN_PARAM_TABLE_NAME
);
1431 rSh
.MoveTable( GotoCurrTable
, fnTableStart
);
1433 rSh
.MoveTable( GotoCurrTable
, fnTableEnd
);
1435 ItemSetToTableParam( *m_pTableSet
, rSh
);
1438 rSh
.MoveTable( GotoCurrTable
, fnTableStart
);
1441 static Sequence
<OUString
> lcl_createSourceNames(std::u16string_view rNodeName
)
1443 Sequence
<OUString
> aSourceNames(11);
1444 OUString
* pNames
= aSourceNames
.getArray();
1445 pNames
[0] = OUString::Concat(rNodeName
) + "/DataSource";
1446 pNames
[1] = OUString::Concat(rNodeName
) + "/Command";
1447 pNames
[2] = OUString::Concat(rNodeName
) + "/CommandType";
1448 pNames
[3] = OUString::Concat(rNodeName
) + "/ColumnsToText";
1449 pNames
[4] = OUString::Concat(rNodeName
) + "/ColumnsToTable";
1450 pNames
[5] = OUString::Concat(rNodeName
) + "/ParaStyle";
1451 pNames
[6] = OUString::Concat(rNodeName
) + "/TableAutoFormat";
1452 pNames
[7] = OUString::Concat(rNodeName
) + "/IsTable";
1453 pNames
[8] = OUString::Concat(rNodeName
) + "/IsField";
1454 pNames
[9] = OUString::Concat(rNodeName
) + "/IsHeadlineOn";
1455 pNames
[10] = OUString::Concat(rNodeName
) + "/IsEmptyHeadline";
1456 return aSourceNames
;
1459 static Sequence
<OUString
> lcl_CreateSubNames(std::u16string_view rSubNodeName
)
1463 OUString::Concat(rSubNodeName
) + "/ColumnName",
1464 OUString::Concat(rSubNodeName
) + "/ColumnIndex",
1465 OUString::Concat(rSubNodeName
) + "/IsNumberFormat",
1466 OUString::Concat(rSubNodeName
) + "/IsNumberFormatFromDataBase",
1467 OUString::Concat(rSubNodeName
) + "/NumberFormat",
1468 OUString::Concat(rSubNodeName
) + "/NumberFormatLocale"
1472 static OUString
lcl_CreateUniqueName(const Sequence
<OUString
>& aNames
)
1474 sal_Int32 nIdx
= aNames
.getLength();
1477 const OUString sRet
= "_" + OUString::number(nIdx
++);
1478 if ( comphelper::findValue(aNames
, sRet
) == -1 )
1479 return sRet
; // No match found, return unique name
1483 void SwInsertDBColAutoPilot::Notify( const css::uno::Sequence
< OUString
>& ) {}
1485 void SwInsertDBColAutoPilot::ImplCommit()
1487 Sequence
<OUString
> aNames
= GetNodeNames(OUString());
1488 //remove entries that contain this data source + table at first
1489 for (OUString
const& nodeName
: aNames
)
1491 Sequence
<Any
> aSourceProperties
= GetProperties({ nodeName
+ "/DataSource", nodeName
+ "/Command" });
1492 const Any
* pSourceProps
= aSourceProperties
.getArray();
1493 OUString sSource
, sCommand
;
1494 pSourceProps
[0] >>= sSource
;
1495 pSourceProps
[1] >>= sCommand
;
1496 if(sSource
==m_aDBData
.sDataSource
&& sCommand
==m_aDBData
.sCommand
)
1498 ClearNodeElements(OUString(), { nodeName
});
1502 aNames
= GetNodeNames(OUString());
1503 OUString sNewNode
= lcl_CreateUniqueName(aNames
);
1504 Sequence
<OUString
> aNodeNames
= lcl_createSourceNames(sNewNode
);
1505 Sequence
<PropertyValue
> aValues(aNodeNames
.getLength());
1506 PropertyValue
* pValues
= aValues
.getArray();
1507 const OUString
* pNodeNames
= aNodeNames
.getConstArray();
1508 for(sal_Int32 i
= 0; i
< aNodeNames
.getLength(); i
++)
1510 pValues
[i
].Name
= "/" + pNodeNames
[i
];
1513 pValues
[0].Value
<<= m_aDBData
.sDataSource
;
1514 pValues
[1].Value
<<= m_aDBData
.sCommand
;
1515 pValues
[2].Value
<<= m_aDBData
.nCommandType
;
1516 pValues
[3].Value
<<= m_xEdDbText
->get_text();
1519 const sal_Int32 nCnt
= m_xLbTableCol
->n_children();
1520 for( sal_Int32 n
= 0; n
< nCnt
; ++n
)
1521 sTmp
+= m_xLbTableCol
->get_text(n
) + "\x0a";
1523 if (!sTmp
.isEmpty())
1524 pValues
[4].Value
<<= sTmp
;
1526 if( m_sNoTmpl
!= (sTmp
= m_xLbDbParaColl
->get_active_text()) )
1527 pValues
[5].Value
<<= sTmp
;
1530 pValues
[6].Value
<<= m_xTAutoFormat
->GetName();
1532 pValues
[7].Value
<<= m_xRbAsTable
->get_active();
1533 pValues
[8].Value
<<= m_xRbAsField
->get_active();
1534 pValues
[9].Value
<<= m_xCbTableHeadon
->get_active();
1535 pValues
[10].Value
<<= m_xRbHeadlEmpty
->get_active();
1537 SetSetProperties(OUString(), aValues
);
1539 sNewNode
+= "/ColumnSet";
1541 LanguageType
ePrevLang(0xffff);
1543 SvNumberFormatter
& rNFormatr
= *m_pView
->GetWrtShell().GetNumberFormatter();
1544 for(size_t nCol
= 0; nCol
< m_aDBColumns
.size(); nCol
++)
1546 SwInsDBColumn
* pColumn
= m_aDBColumns
[nCol
].get();
1547 OUString
sColumnInsertNode(sNewNode
+ "/__");
1549 sColumnInsertNode
+= "00";
1550 else if( nCol
< 100 )
1551 sColumnInsertNode
+= "0";
1552 sColumnInsertNode
+= OUString::number( nCol
);
1554 const Sequence
<OUString
> aSubNodeNames
= lcl_CreateSubNames(sColumnInsertNode
);
1555 Sequence
<PropertyValue
> aSubValues(aSubNodeNames
.getLength());
1556 PropertyValue
* pSubValues
= aSubValues
.getArray();
1559 for( const OUString
& rSubNodeName
: aSubNodeNames
)
1560 pSubValues
[i
++].Name
= rSubNodeName
;
1561 pSubValues
[0].Value
<<= pColumn
->sColumn
;
1562 pSubValues
[1].Value
<<= i
;
1563 pSubValues
[2].Value
<<= pColumn
->bHasFormat
;
1564 pSubValues
[3].Value
<<= pColumn
->bIsDBFormat
;
1566 SwStyleNameMapper::FillUIName( RES_POOLCOLL_STANDARD
, sTmp
);
1567 const SvNumberformat
* pNF
= rNFormatr
.GetEntry( pColumn
->nUsrNumFormat
);
1571 pSubValues
[4].Value
<<= pNF
->GetFormatstring();
1572 eLang
= pNF
->GetLanguage();
1576 pSubValues
[4].Value
<<= sTmp
;
1577 eLang
= GetAppLanguage();
1581 if( eLang
!= ePrevLang
)
1583 sPrevLang
= LanguageTag::convertToBcp47( eLang
);
1587 pSubValues
[5].Value
<<= sPrevLang
;
1588 SetSetProperties(sNewNode
, aSubValues
);
1592 void SwInsertDBColAutoPilot::Load()
1594 const Sequence
<OUString
> aNames
= GetNodeNames(OUString());
1595 SvNumberFormatter
& rNFormatr
= *m_pView
->GetWrtShell().GetNumberFormatter();
1596 for(OUString
const & nodeName
: aNames
)
1598 //search for entries with the appropriate data source and table
1599 Sequence
<OUString
> aSourceNames
= lcl_createSourceNames(nodeName
);
1601 Sequence
< Any
> aDataSourceProps
= GetProperties(aSourceNames
);
1602 const Any
* pDataSourceProps
= aDataSourceProps
.getConstArray();
1603 OUString sSource
, sCommand
;
1604 sal_Int16 nCommandType
;
1605 pDataSourceProps
[0] >>= sSource
;
1606 pDataSourceProps
[1] >>= sCommand
;
1607 pDataSourceProps
[2] >>= nCommandType
;
1608 if(sSource
== m_aDBData
.sDataSource
&& sCommand
== m_aDBData
.sCommand
)
1610 DB_ColumnConfigData aNewData
;
1612 pDataSourceProps
[3] >>= aNewData
.sEdit
;
1613 pDataSourceProps
[4] >>= aNewData
.sTableList
;
1614 pDataSourceProps
[5] >>= aNewData
.sTmplNm
;
1615 pDataSourceProps
[6] >>= aNewData
.sTAutoFormatNm
;
1616 if(pDataSourceProps
[7].hasValue())
1617 aNewData
.bIsTable
= *o3tl::doAccess
<bool>(pDataSourceProps
[7]);
1618 if(pDataSourceProps
[8].hasValue())
1619 aNewData
.bIsField
= *o3tl::doAccess
<bool>(pDataSourceProps
[8]);
1620 if(pDataSourceProps
[9].hasValue())
1621 aNewData
.bIsHeadlineOn
= *o3tl::doAccess
<bool>(pDataSourceProps
[9]);
1622 if(pDataSourceProps
[10].hasValue())
1623 aNewData
.bIsEmptyHeadln
= *o3tl::doAccess
<bool>(pDataSourceProps
[10]);
1625 const OUString
sSubNodeName(nodeName
+ "/ColumnSet/");
1626 const Sequence
<OUString
> aSubNames
= GetNodeNames(sSubNodeName
);
1627 for(const OUString
& rSubName
: aSubNames
)
1629 Sequence
<OUString
> aSubNodeNames
=
1630 lcl_CreateSubNames(Concat2View(sSubNodeName
+ rSubName
));
1631 Sequence
< Any
> aSubProps
= GetProperties(aSubNodeNames
);
1632 const Any
* pSubProps
= aSubProps
.getConstArray();
1635 pSubProps
[0] >>= sColumn
;
1636 // check for existence of the loaded column name
1637 bool bFound
= false;
1638 for(size_t nRealColumn
= 0; nRealColumn
< m_aDBColumns
.size(); ++nRealColumn
)
1640 if(m_aDBColumns
[nRealColumn
]->sColumn
== sColumn
)
1648 sal_Int16 nIndex
= 0;
1649 pSubProps
[1] >>= nIndex
;
1650 std::unique_ptr
<SwInsDBColumn
> pInsDBColumn(new SwInsDBColumn(sColumn
));
1651 if(pSubProps
[2].hasValue())
1652 pInsDBColumn
->bHasFormat
= *o3tl::doAccess
<bool>(pSubProps
[2]);
1653 if(pSubProps
[3].hasValue())
1654 pInsDBColumn
->bIsDBFormat
= *o3tl::doAccess
<bool>(pSubProps
[3]);
1656 pSubProps
[4] >>= pInsDBColumn
->sUsrNumFormat
;
1657 OUString sNumberFormatLocale
;
1658 pSubProps
[5] >>= sNumberFormatLocale
;
1660 /* XXX Earlier versions wrote a Country-Language string in
1661 * SwInsertDBColAutoPilot::Commit() that here was read as
1662 * Language-Country with 2 characters copied to language,
1663 * 1 character separator and unconditionally 2 characters read
1664 * as country. So for 'DE-de' and locales that have similar
1665 * case-insensitive equal language/country combos that may have
1666 * worked, for all others not. FIXME if you need to read old
1667 * data that you were never able to read before. */
1668 pInsDBColumn
->eUsrNumFormatLng
= LanguageTag::convertToLanguageType( sNumberFormatLocale
);
1670 pInsDBColumn
->nUsrNumFormat
= rNFormatr
.GetEntryKey( pInsDBColumn
->sUsrNumFormat
,
1671 pInsDBColumn
->eUsrNumFormatLng
);
1673 aNewData
.aDBColumns
.insert(std::move(pInsDBColumn
));
1675 OUString
sTmp( aNewData
.sTableList
);
1676 if( !sTmp
.isEmpty() )
1680 const OUString
sEntry( sTmp
.getToken( 0, '\x0a', n
) );
1681 //preselect column - if they still exist!
1682 if (m_xLbTableDbColumn
->find_text(sEntry
) != -1)
1684 m_xLbTableCol
->append_text(sEntry
);
1685 m_xLbTableDbColumn
->remove_text(sEntry
);
1689 if (!m_xLbTableDbColumn
->n_children())
1691 m_xIbDbcolAllTo
->set_sensitive( false );
1692 m_xIbDbcolOneTo
->set_sensitive( false );
1694 m_xIbDbcolOneFrom
->set_sensitive(true);
1695 m_xIbDbcolAllFrom
->set_sensitive(true);
1697 m_xEdDbText
->set_text( aNewData
.sEdit
);
1699 sTmp
= aNewData
.sTmplNm
;
1700 if( !sTmp
.isEmpty() )
1701 m_xLbDbParaColl
->set_active_text(sTmp
);
1703 m_xLbDbParaColl
->set_active(0);
1705 m_xTAutoFormat
.reset();
1706 sTmp
= aNewData
.sTAutoFormatNm
;
1707 if( !sTmp
.isEmpty() )
1709 // then load the AutoFormat file and look for Autoformat first
1710 SwTableAutoFormatTable aAutoFormatTable
;
1711 aAutoFormatTable
.Load();
1712 for( size_t nAutoFormat
= aAutoFormatTable
.size(); nAutoFormat
; )
1713 if( sTmp
== aAutoFormatTable
[ --nAutoFormat
].GetName() )
1715 m_xTAutoFormat
.reset(new SwTableAutoFormat(aAutoFormatTable
[nAutoFormat
]));
1720 m_xRbAsTable
->set_active( aNewData
.bIsTable
);
1721 m_xRbAsField
->set_active( aNewData
.bIsField
);
1722 m_xRbAsText
->set_active( !aNewData
.bIsTable
&& !aNewData
.bIsField
);
1724 m_xCbTableHeadon
->set_active( aNewData
.bIsHeadlineOn
);
1725 m_xRbHeadlColnms
->set_active( !aNewData
.bIsEmptyHeadln
);
1726 m_xRbHeadlEmpty
->set_active( aNewData
.bIsEmptyHeadln
);
1727 HeaderHdl(*m_xCbTableHeadon
);
1729 // now copy the user defined Numberformat strings to the
1730 // Shell. Then only these are available as ID
1731 for( size_t n
= 0; n
< m_aDBColumns
.size() ; ++n
)
1733 SwInsDBColumn
& rSet
= *m_aDBColumns
[ n
];
1734 for( size_t m
= 0; m
< aNewData
.aDBColumns
.size() ; ++m
)
1736 SwInsDBColumn
& rGet
= *aNewData
.aDBColumns
[ m
];
1737 if(rGet
.sColumn
== rSet
.sColumn
)
1739 if( rGet
.bHasFormat
&& !rGet
.bIsDBFormat
)
1741 rSet
.bIsDBFormat
= false;
1742 rSet
.nUsrNumFormat
= rNFormatr
.GetEntryKey( rGet
.sUsrNumFormat
,
1743 rGet
.eUsrNumFormatLng
);
1744 if( NUMBERFORMAT_ENTRY_NOT_FOUND
== rSet
.nUsrNumFormat
)
1746 sal_Int32 nCheckPos
;
1747 SvNumFormatType nType
;
1748 rNFormatr
.PutEntry( rGet
.sUsrNumFormat
, nCheckPos
, nType
,
1749 rSet
.nUsrNumFormat
, rGet
.eUsrNumFormatLng
);
1757 // when the cursor is inside of a table, table must NEVER be selectable
1758 if( !m_xRbAsTable
->get_sensitive() && m_xRbAsTable
->get_active() )
1759 m_xRbAsField
->set_active(true);
1765 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */