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 <sal/config.h>
22 #include <string_view>
24 #include <scitems.hxx>
25 #include <editeng/eeitem.hxx>
28 #include <vcl/svapp.hxx>
29 #include <editeng/boxitem.hxx>
30 #include <editeng/brushitem.hxx>
31 #include <editeng/colritem.hxx>
32 #include <editeng/crossedoutitem.hxx>
33 #include <editeng/fhgtitem.hxx>
34 #include <editeng/fontitem.hxx>
35 #include <editeng/postitem.hxx>
36 #include <editeng/udlnitem.hxx>
37 #include <editeng/wghtitem.hxx>
38 #include <editeng/justifyitem.hxx>
39 #include <svx/xoutbmp.hxx>
40 #include <editeng/editeng.hxx>
41 #include <svtools/htmlcfg.hxx>
42 #include <sfx2/docfile.hxx>
43 #include <sfx2/frmhtmlw.hxx>
44 #include <sfx2/objsh.hxx>
45 #include <svl/urihelper.hxx>
46 #include <svtools/htmlkywd.hxx>
47 #include <svtools/htmlout.hxx>
48 #include <svtools/parhtml.hxx>
49 #include <vcl/outdev.hxx>
51 #include <osl/diagnose.h>
52 #include <o3tl/unit_conversion.hxx>
53 #include <o3tl/string_view.hxx>
55 #include <htmlexp.hxx>
58 #include <document.hxx>
61 #include <patattr.hxx>
62 #include <stlpool.hxx>
63 #include <scresid.hxx>
64 #include <formulacell.hxx>
65 #include <cellform.hxx>
66 #include <docoptio.hxx>
67 #include <editutil.hxx>
69 #include <cellvalue.hxx>
70 #include <conditio.hxx>
71 #include <colorscale.hxx>
72 #include <mtvelements.hxx>
74 #include <editeng/flditem.hxx>
75 #include <editeng/borderline.hxx>
77 // Without strings.hrc: error C2679: binary '=' : no operator defined which takes a
78 // right-hand operand of type 'const class String (__stdcall *)(class ScResId)'
80 // const String aStrTable( ScResId( SCSTR_TABLE ) ); aStrOut = aStrTable;
82 #include <strings.hrc>
83 #include <globstr.hrc>
85 #include <com/sun/star/frame/XModel.hpp>
86 #include <com/sun/star/uno/Reference.h>
87 #include <com/sun/star/document/XDocumentProperties.hpp>
88 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
89 #include <rtl/strbuf.hxx>
90 #include <officecfg/Office/Common.hxx>
91 #include <tools/json_writer.hxx>
92 #include <svl/numformat.hxx>
93 #include <svl/zformat.hxx>
95 using ::editeng::SvxBorderLine
;
96 using namespace ::com::sun::star
;
98 const char sMyBegComment
[] = "<!-- ";
99 const char sMyEndComment
[] = " -->";
100 const char sDisplay
[] = "display:";
101 const char sBorder
[] = "border:";
102 const char sBackground
[] = "background:";
104 const sal_uInt16
ScHTMLExport::nDefaultFontSize
[SC_HTML_FONTSIZES
] =
106 HTMLFONTSZ1_DFLT
, HTMLFONTSZ2_DFLT
, HTMLFONTSZ3_DFLT
, HTMLFONTSZ4_DFLT
,
107 HTMLFONTSZ5_DFLT
, HTMLFONTSZ6_DFLT
, HTMLFONTSZ7_DFLT
110 sal_uInt16
ScHTMLExport::nFontSize
[SC_HTML_FONTSIZES
] = { 0 };
112 const char* ScHTMLExport::pFontSizeCss
[SC_HTML_FONTSIZES
] =
114 "xx-small", "x-small", "small", "medium", "large", "x-large", "xx-large"
117 const sal_uInt16
ScHTMLExport::nCellSpacing
= 0;
118 const char ScHTMLExport::sIndentSource
[nIndentMax
+1] =
119 "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t";
121 // Macros for HTML export
123 #define TAG_ON( tag ) HTMLOutFuncs::Out_AsciiTag( rStrm, tag )
124 #define TAG_OFF( tag ) HTMLOutFuncs::Out_AsciiTag( rStrm, tag, false )
125 #define OUT_STR( str ) HTMLOutFuncs::Out_String( rStrm, str, &aNonConvertibleChars )
126 #define OUT_LF() rStrm.WriteOString( SAL_NEWLINE_STRING ).WriteOString( GetIndentStr() )
127 #define TAG_ON_LF( tag ) (TAG_ON( tag ).WriteOString( SAL_NEWLINE_STRING ).WriteOString( GetIndentStr() ))
128 #define TAG_OFF_LF( tag ) (TAG_OFF( tag ).WriteOString( SAL_NEWLINE_STRING ).WriteOString( GetIndentStr() ))
129 #define OUT_HR() TAG_ON_LF( OOO_STRING_SVTOOLS_HTML_horzrule )
130 #define OUT_COMMENT( comment ) (rStrm.WriteOString( sMyBegComment ), OUT_STR( comment ) \
131 .WriteOString( sMyEndComment ).WriteOString( SAL_NEWLINE_STRING ) \
132 .WriteOString( GetIndentStr() ))
134 #define OUT_SP_CSTR_ASS( s ) rStrm.WriteChar(' ').WriteOString( s ).WriteChar( '=' )
136 #define GLOBSTR(id) ScResId( id )
138 void ScFormatFilterPluginImpl::ScExportHTML( SvStream
& rStrm
, const OUString
& rBaseURL
, ScDocument
* pDoc
,
139 const ScRange
& rRange
, const rtl_TextEncoding
/*eNach*/, bool bAll
,
140 const OUString
& rStreamPath
, OUString
& rNonConvertibleChars
, const OUString
& rFilterOptions
)
142 ScHTMLExport
aEx( rStrm
, rBaseURL
, pDoc
, rRange
, bAll
, rStreamPath
, rFilterOptions
);
144 rNonConvertibleChars
= aEx
.GetNonConvertibleChars();
147 static OString
lcl_getColGroupString(sal_Int32 nSpan
, sal_Int32 nWidth
)
149 OStringBuffer
aByteStr(OString::Concat(OOO_STRING_SVTOOLS_HTML_colgroup
)
153 aByteStr
.append(OString::Concat(OOO_STRING_SVTOOLS_HTML_O_span
)
155 + OString::number(nSpan
)
158 aByteStr
.append(OString::Concat(OOO_STRING_SVTOOLS_HTML_O_width
)
160 + OString::number(nWidth
)
162 return aByteStr
.makeStringAndClear();
165 static void lcl_AddStamp( OUString
& rStr
, std::u16string_view rName
,
166 const css::util::DateTime
& rDateTime
,
167 const LocaleDataWrapper
& rLoc
)
169 Date
aD(rDateTime
.Day
, rDateTime
.Month
, rDateTime
.Year
);
170 tools::Time
aT(rDateTime
.Hours
, rDateTime
.Minutes
, rDateTime
.Seconds
,
171 rDateTime
.NanoSeconds
);
172 DateTime
aDateTime(aD
,aT
);
174 OUString aStrDate
= rLoc
.getDate( aDateTime
);
175 OUString aStrTime
= rLoc
.getTime( aDateTime
);
177 rStr
+= GLOBSTR( STR_BY
) + " ";
182 rStr
+= " " + GLOBSTR( STR_ON
) + " ";
183 if (!aStrDate
.isEmpty())
188 if (!aStrTime
.isEmpty())
194 static OString
lcl_makeHTMLColorTriplet(const Color
& rColor
)
198 // <font COLOR="#00FF40">hello</font>
199 snprintf( buf
, 24, "\"#%02X%02X%02X\"", rColor
.GetRed(), rColor
.GetGreen(), rColor
.GetBlue() );
204 ScHTMLExport::ScHTMLExport( SvStream
& rStrmP
, OUString _aBaseURL
, ScDocument
* pDocP
,
205 const ScRange
& rRangeP
, bool bAllP
,
206 OUString aStreamPathP
, std::u16string_view rFilterOptions
) :
207 ScExportBase( rStrmP
, pDocP
, rRangeP
),
208 aBaseURL(std::move( _aBaseURL
)),
209 aStreamPath(std::move( aStreamPathP
)),
210 pAppWin( Application::GetDefaultDevice() ),
214 bTabHasGraphics( false ),
215 bTabAlignedLeft( false ),
216 bCalcAsShown( pDocP
->GetDocOptions().IsCalcAsShown() ),
217 bTableDataHeight( true ),
218 mbSkipImages ( false ),
219 mbSkipHeaderFooter( false )
221 strcpy( sIndent
, sIndentSource
);
224 // set HTML configuration
225 bCopyLocalFileToINet
= officecfg::Office::Common::Filter::HTML::Export::LocalGraphic::get();
227 if (rFilterOptions
== u
"SkipImages")
231 else if (rFilterOptions
== u
"SkipHeaderFooter")
233 mbSkipHeaderFooter
= true;
236 for ( sal_uInt16 j
=0; j
< SC_HTML_FONTSIZES
; j
++ )
238 sal_uInt16 nSize
= SvxHtmlOptions::GetFontSize( j
);
239 // remember in Twips, like our SvxFontHeightItem
241 nFontSize
[j
] = nSize
* 20;
243 nFontSize
[j
] = nDefaultFontSize
[j
] * 20;
246 const SCTAB nCount
= pDoc
->GetTableCount();
247 for ( SCTAB nTab
= 0; nTab
< nCount
; nTab
++ )
249 if ( !IsEmptyTable( nTab
) )
254 ScHTMLExport::~ScHTMLExport()
259 sal_uInt16
ScHTMLExport::GetFontSizeNumber( sal_uInt16 nHeight
)
261 sal_uInt16 nSize
= 1;
262 for ( sal_uInt16 j
=SC_HTML_FONTSIZES
-1; j
>0; j
-- )
264 if( nHeight
> (nFontSize
[j
] + nFontSize
[j
-1]) / 2 )
265 { // The one next to it
273 const char* ScHTMLExport::GetFontSizeCss( sal_uInt16 nHeight
)
275 sal_uInt16 nSize
= GetFontSizeNumber( nHeight
);
276 return pFontSizeCss
[ nSize
-1 ];
279 sal_uInt16
ScHTMLExport::ToPixel( sal_uInt16 nVal
)
283 nVal
= static_cast<sal_uInt16
>(pAppWin
->LogicToPixel(
284 Size( nVal
, nVal
), MapMode( MapUnit::MapTwip
) ).Width());
285 if( !nVal
) // If there's a Twip there should also be a Pixel
291 Size
ScHTMLExport::MMToPixel( const Size
& rSize
)
293 Size aSize
= pAppWin
->LogicToPixel( rSize
, MapMode( MapUnit::Map100thMM
) );
294 // If there's something there should also be a Pixel
295 if ( !aSize
.Width() && rSize
.Width() )
297 if ( !aSize
.Height() && rSize
.Height() )
298 aSize
.setHeight( 1 );
302 void ScHTMLExport::Write()
304 if (!mbSkipHeaderFooter
)
306 rStrm
.WriteChar( '<' ).WriteOString( OOO_STRING_SVTOOLS_HTML_doctype
).WriteChar( ' ' ).WriteOString( OOO_STRING_SVTOOLS_HTML_doctype5
).WriteChar( '>' )
307 .WriteOString( SAL_NEWLINE_STRING
).WriteOString( SAL_NEWLINE_STRING
);
308 TAG_ON_LF( OOO_STRING_SVTOOLS_HTML_html
);
314 if (!mbSkipHeaderFooter
)
315 TAG_OFF_LF( OOO_STRING_SVTOOLS_HTML_html
);
318 void ScHTMLExport::WriteHeader()
320 IncIndent(1); TAG_ON_LF( OOO_STRING_SVTOOLS_HTML_head
);
322 if ( pDoc
->IsClipOrUndo() )
323 { // no real DocInfo available, but some META information like charset needed
324 SfxFrameHTMLWriter::Out_DocInfo( rStrm
, aBaseURL
, nullptr, sIndent
, &aNonConvertibleChars
);
328 uno::Reference
<document::XDocumentPropertiesSupplier
> xDPS(
329 static_cast<cppu::OWeakObject
*>(pDoc
->GetDocumentShell()->GetModel()), uno::UNO_QUERY_THROW
);
330 uno::Reference
<document::XDocumentProperties
> xDocProps
331 = xDPS
->getDocumentProperties();
332 SfxFrameHTMLWriter::Out_DocInfo( rStrm
, aBaseURL
, xDocProps
,
333 sIndent
, &aNonConvertibleChars
);
336 if (!xDocProps
->getPrintedBy().isEmpty())
338 OUT_COMMENT( GLOBSTR( STR_DOC_INFO
) );
339 OUString aStrOut
= GLOBSTR( STR_DOC_PRINTED
) + ": ";
340 lcl_AddStamp( aStrOut
, xDocProps
->getPrintedBy(),
341 xDocProps
->getPrintDate(), ScGlobal::getLocaleData() );
342 OUT_COMMENT( aStrOut
);
349 PageDefaults( bAll
? 0 : aRange
.aStart
.Tab() );
351 rStrm
.WriteOString( "<" ).WriteOString( OOO_STRING_SVTOOLS_HTML_style
).WriteOString( " " ).WriteOString( OOO_STRING_SVTOOLS_HTML_O_type
).WriteOString( "=\"text/css\">" );
354 rStrm
.WriteOString(OOO_STRING_SVTOOLS_HTML_body
);
355 rStrm
.WriteOString(",");
356 rStrm
.WriteOString(OOO_STRING_SVTOOLS_HTML_division
);
357 rStrm
.WriteOString(",");
358 rStrm
.WriteOString(OOO_STRING_SVTOOLS_HTML_table
);
359 rStrm
.WriteOString(",");
360 rStrm
.WriteOString(OOO_STRING_SVTOOLS_HTML_thead
);
361 rStrm
.WriteOString(",");
362 rStrm
.WriteOString(OOO_STRING_SVTOOLS_HTML_tbody
);
363 rStrm
.WriteOString(",");
364 rStrm
.WriteOString(OOO_STRING_SVTOOLS_HTML_tfoot
);
365 rStrm
.WriteOString(",");
366 rStrm
.WriteOString(OOO_STRING_SVTOOLS_HTML_tablerow
);
367 rStrm
.WriteOString(",");
368 rStrm
.WriteOString(OOO_STRING_SVTOOLS_HTML_tableheader
);
369 rStrm
.WriteOString(",");
370 rStrm
.WriteOString(OOO_STRING_SVTOOLS_HTML_tabledata
);
371 rStrm
.WriteOString(",");
372 rStrm
.WriteOString(OOO_STRING_SVTOOLS_HTML_parabreak
);
373 rStrm
.WriteOString(" { ");
374 rStrm
.WriteOString("font-family:");
376 if (!aHTMLStyle
.aFontFamilyName
.isEmpty())
378 const OUString
& rList
= aHTMLStyle
.aFontFamilyName
;
379 for(sal_Int32 nPos
{0};;)
381 rStrm
.WriteChar( '\"' );
382 OUT_STR( o3tl::getToken( rList
, 0, ';', nPos
) );
383 rStrm
.WriteChar( '\"' );
386 rStrm
.WriteOString( ", " );
389 rStrm
.WriteOString("; ");
390 rStrm
.WriteOString("font-size:");
391 rStrm
.WriteOString(GetFontSizeCss(static_cast<sal_uInt16
>(aHTMLStyle
.nFontHeight
)));
392 rStrm
.WriteOString(" }");
396 // write the style for the comments to make them stand out from normal cell content
397 // this is done through only showing the cell contents when the custom indicator is hovered
398 rStrm
.WriteOString(OOO_STRING_SVTOOLS_HTML_anchor
);
399 rStrm
.WriteOString(".comment-indicator:hover");
400 rStrm
.WriteOString(" + ");
401 rStrm
.WriteOString(OOO_STRING_SVTOOLS_HTML_comment2
);
402 rStrm
.WriteOString(" { ");
403 rStrm
.WriteOString(sBackground
);
404 rStrm
.WriteOString("#ffd");
405 rStrm
.WriteOString("; ");
406 rStrm
.WriteOString("position:");
407 rStrm
.WriteOString("absolute");
408 rStrm
.WriteOString("; ");
409 rStrm
.WriteOString(sDisplay
);
410 rStrm
.WriteOString("block");
411 rStrm
.WriteOString("; ");
412 rStrm
.WriteOString(sBorder
);
413 rStrm
.WriteOString("1px solid black");
414 rStrm
.WriteOString("; ");
415 rStrm
.WriteOString("padding:");
416 rStrm
.WriteOString("0.5em");
417 rStrm
.WriteOString("; ");
418 rStrm
.WriteOString(" } ");
422 rStrm
.WriteOString(OOO_STRING_SVTOOLS_HTML_anchor
);
423 rStrm
.WriteOString(".comment-indicator");
424 rStrm
.WriteOString(" { ");
425 rStrm
.WriteOString(sBackground
);
426 rStrm
.WriteOString("red");
427 rStrm
.WriteOString("; ");
428 rStrm
.WriteOString(sDisplay
);
429 rStrm
.WriteOString("inline-block");
430 rStrm
.WriteOString("; ");
431 rStrm
.WriteOString(sBorder
);
432 rStrm
.WriteOString("1px solid black");
433 rStrm
.WriteOString("; ");
434 rStrm
.WriteOString("width:");
435 rStrm
.WriteOString("0.5em");
436 rStrm
.WriteOString("; ");
437 rStrm
.WriteOString("height:");
438 rStrm
.WriteOString("0.5em");
439 rStrm
.WriteOString("; ");
440 rStrm
.WriteOString(" } ");
444 rStrm
.WriteOString(OOO_STRING_SVTOOLS_HTML_comment2
);
445 rStrm
.WriteOString(" { ");
446 rStrm
.WriteOString(sDisplay
);
447 rStrm
.WriteOString("none");
448 rStrm
.WriteOString("; ");
449 rStrm
.WriteOString(" } ");
454 TAG_OFF_LF( OOO_STRING_SVTOOLS_HTML_style
);
458 TAG_OFF_LF( OOO_STRING_SVTOOLS_HTML_head
);
461 void ScHTMLExport::WriteOverview()
463 if ( nUsedTables
<= 1 )
468 IncIndent(1); TAG_ON( OOO_STRING_SVTOOLS_HTML_parabreak
); TAG_ON_LF( OOO_STRING_SVTOOLS_HTML_center
);
469 TAG_ON( OOO_STRING_SVTOOLS_HTML_head1
);
470 OUT_STR( ScResId( STR_OVERVIEW
) );
471 TAG_OFF_LF( OOO_STRING_SVTOOLS_HTML_head1
);
475 const SCTAB nCount
= pDoc
->GetTableCount();
476 for ( SCTAB nTab
= 0; nTab
< nCount
; nTab
++ )
478 if ( !IsEmptyTable( nTab
) )
480 pDoc
->GetName( nTab
, aStr
);
481 rStrm
.WriteOString( "<A HREF=\"#table" )
482 .WriteOString( OString::number(nTab
) )
483 .WriteOString( "\">" );
485 rStrm
.WriteOString( "</A>" );
486 TAG_ON_LF( OOO_STRING_SVTOOLS_HTML_linebreak
);
490 IncIndent(-1); OUT_LF();
491 IncIndent(-1); TAG_OFF( OOO_STRING_SVTOOLS_HTML_center
); TAG_OFF_LF( OOO_STRING_SVTOOLS_HTML_parabreak
);
494 const SfxItemSet
& ScHTMLExport::PageDefaults( SCTAB nTab
)
496 SfxStyleSheetBasePool
* pStylePool
= pDoc
->GetStyleSheetPool();
497 SfxStyleSheetBase
* pStyleSheet
= nullptr;
498 OSL_ENSURE( pStylePool
, "StylePool not found! :-(" );
500 // remember defaults for compare in WriteCell
501 if ( !aHTMLStyle
.bInitialized
)
503 pStyleSheet
= pStylePool
->Find(
504 ScResId(STR_STYLENAME_STANDARD
),
505 SfxStyleFamily::Para
);
506 OSL_ENSURE( pStyleSheet
, "ParaStyle not found! :-(" );
508 pStyleSheet
= pStylePool
->First(SfxStyleFamily::Para
);
509 const SfxItemSet
& rSetPara
= pStyleSheet
->GetItemSet();
511 aHTMLStyle
.nDefaultScriptType
= ScGlobal::GetDefaultScriptType();
512 aHTMLStyle
.aFontFamilyName
= static_cast<const SvxFontItem
&>((rSetPara
.Get(
513 ScGlobal::GetScriptedWhichID(
514 aHTMLStyle
.nDefaultScriptType
, ATTR_FONT
515 )))).GetFamilyName();
516 aHTMLStyle
.nFontHeight
= static_cast<const SvxFontHeightItem
&>((rSetPara
.Get(
517 ScGlobal::GetScriptedWhichID(
518 aHTMLStyle
.nDefaultScriptType
, ATTR_FONT_HEIGHT
520 aHTMLStyle
.nFontSizeNumber
= GetFontSizeNumber( static_cast< sal_uInt16
>( aHTMLStyle
.nFontHeight
) );
523 // Page style sheet printer settings, e.g. for background graphics.
524 // There's only one background graphic in HTML!
525 pStyleSheet
= pStylePool
->Find( pDoc
->GetPageStyle( nTab
), SfxStyleFamily::Page
);
526 OSL_ENSURE( pStyleSheet
, "PageStyle not found! :-(" );
528 pStyleSheet
= pStylePool
->First(SfxStyleFamily::Page
);
529 const SfxItemSet
& rSet
= pStyleSheet
->GetItemSet();
530 if ( !aHTMLStyle
.bInitialized
)
532 const SvxBrushItem
* pBrushItem
= &rSet
.Get( ATTR_BACKGROUND
);
533 aHTMLStyle
.aBackgroundColor
= pBrushItem
->GetColor();
534 aHTMLStyle
.bInitialized
= true;
539 OString
ScHTMLExport::BorderToStyle(const char* pBorderName
,
540 const SvxBorderLine
* pLine
, bool& bInsertSemicolon
)
546 if ( bInsertSemicolon
)
550 aOut
.append(OString::Concat("border-") + pBorderName
+ ": ");
553 int nWidth
= pLine
->GetWidth();
554 int nPxWidth
= (nWidth
> 0) ?
555 std::max(o3tl::convert(nWidth
, o3tl::Length::twip
, o3tl::Length::px
), sal_Int64(1)) : 0;
556 aOut
.append(OString::number(nPxWidth
) + "px ");
557 switch (pLine
->GetBorderLineStyle())
559 case SvxBorderLineStyle::SOLID
:
560 aOut
.append("solid");
562 case SvxBorderLineStyle::DOTTED
:
563 aOut
.append("dotted");
565 case SvxBorderLineStyle::DASHED
:
566 case SvxBorderLineStyle::DASH_DOT
:
567 case SvxBorderLineStyle::DASH_DOT_DOT
:
568 aOut
.append("dashed");
570 case SvxBorderLineStyle::DOUBLE
:
571 case SvxBorderLineStyle::DOUBLE_THIN
:
572 case SvxBorderLineStyle::THINTHICK_SMALLGAP
:
573 case SvxBorderLineStyle::THINTHICK_MEDIUMGAP
:
574 case SvxBorderLineStyle::THINTHICK_LARGEGAP
:
575 case SvxBorderLineStyle::THICKTHIN_SMALLGAP
:
576 case SvxBorderLineStyle::THICKTHIN_MEDIUMGAP
:
577 case SvxBorderLineStyle::THICKTHIN_LARGEGAP
:
578 aOut
.append("double");
580 case SvxBorderLineStyle::EMBOSSED
:
581 aOut
.append("ridge");
583 case SvxBorderLineStyle::ENGRAVED
:
584 aOut
.append("groove");
586 case SvxBorderLineStyle::OUTSET
:
587 aOut
.append("outset");
589 case SvxBorderLineStyle::INSET
:
590 aOut
.append("inset");
593 aOut
.append("hidden");
599 snprintf( hex
, 7, "%06" SAL_PRIxUINT32
, static_cast<sal_uInt32
>( pLine
->GetColor().GetRGBColor() ) );
604 bInsertSemicolon
= true;
607 return aOut
.makeStringAndClear();
610 void ScHTMLExport::WriteBody()
612 const SfxItemSet
& rSet
= PageDefaults( bAll
? 0 : aRange
.aStart
.Tab() );
613 const SvxBrushItem
* pBrushItem
= &rSet
.Get( ATTR_BACKGROUND
);
615 // default text color black
616 if (!mbSkipHeaderFooter
)
618 rStrm
.WriteChar( '<' ).WriteOString( OOO_STRING_SVTOOLS_HTML_body
);
622 if ( bAll
&& GPOS_NONE
!= pBrushItem
->GetGraphicPos() )
624 OUString aLink
= pBrushItem
->GetGraphicLink();
627 // Embedded graphic -> write using WriteGraphic
628 if( aLink
.isEmpty() )
630 const Graphic
* pGrf
= pBrushItem
->GetGraphic();
633 // Save graphic as (JPG) file
634 aGrfNm
= aStreamPath
;
635 ErrCode nErr
= XOutBitmap::WriteGraphic( *pGrf
, aGrfNm
,
636 u
"JPG"_ustr
, XOutFlags::UseNativeIfPossible
);
637 if( !nErr
) // Contains errors, as we have nothing to output
639 aGrfNm
= URIHelper::SmartRel2Abs(
640 INetURLObject(aBaseURL
),
641 aGrfNm
, URIHelper::GetMaybeFileHdl());
649 if( bCopyLocalFileToINet
)
651 CopyLocalFileToINet( aGrfNm
, aStreamPath
);
654 aGrfNm
= URIHelper::SmartRel2Abs(
655 INetURLObject(aBaseURL
),
656 aGrfNm
, URIHelper::GetMaybeFileHdl());
659 if( !aLink
.isEmpty() )
661 rStrm
.WriteChar( ' ' ).WriteOString( OOO_STRING_SVTOOLS_HTML_O_background
).WriteOString( "=\"" );
662 OUT_STR( URIHelper::simpleNormalizedMakeRelative(
664 aLink
) ).WriteChar( '\"' );
668 if ( !aHTMLStyle
.aBackgroundColor
.IsTransparent() )
669 { // A transparent background color should always result in default
670 // background of the browser. Also, HTMLOutFuncs::Out_Color() writes
671 // black #000000 for COL_AUTO which is the same as white #ffffff with
672 // transparency set to 0xff, our default background.
673 OUT_SP_CSTR_ASS( OOO_STRING_SVTOOLS_HTML_O_bgcolor
);
674 HTMLOutFuncs::Out_Color( rStrm
, aHTMLStyle
.aBackgroundColor
);
677 rStrm
.WriteChar( '>' ); OUT_LF();
679 // A marker right after <body> can be used, so that data-sheets-* attributes are considered
680 // at all. This is disabled by default.
682 char* pEnv
= getenv("SC_DEBUG_HTML_MARKER");
687 else if (comphelper::LibreOfficeKit::isActive())
689 aMarker
= "<google-sheets-html-origin/>"_ostr
;
691 rStrm
.WriteOString(aMarker
);
699 if (!mbSkipHeaderFooter
)
700 TAG_OFF_LF( OOO_STRING_SVTOOLS_HTML_body
);
703 void ScHTMLExport::WriteTables()
705 const SCTAB nTabCount
= pDoc
->GetTableCount();
706 const OUString
aStrTable( ScResId( SCSTR_TABLE
) );
715 SCCOL nStartColFix
= 0;
716 SCROW nStartRowFix
= 0;
717 SCCOL nEndColFix
= 0;
718 SCROW nEndRowFix
= 0;
719 ScDrawLayer
* pDrawLayer
= pDoc
->GetDrawLayer();
723 nEndTab
= nTabCount
- 1;
727 nStartCol
= nStartColFix
= aRange
.aStart
.Col();
728 nStartRow
= nStartRowFix
= aRange
.aStart
.Row();
729 nStartTab
= aRange
.aStart
.Tab();
730 nEndCol
= nEndColFix
= aRange
.aEnd
.Col();
731 nEndRow
= nEndRowFix
= aRange
.aEnd
.Row();
732 nEndTab
= aRange
.aEnd
.Tab();
734 SCTAB nTableStrNum
= 1;
735 for ( SCTAB nTab
=nStartTab
; nTab
<=nEndTab
; nTab
++ )
737 if ( !pDoc
->IsVisible( nTab
) )
742 if ( !GetDataArea( nTab
, nStartCol
, nStartRow
, nEndCol
, nEndRow
) )
745 if ( nUsedTables
> 1 )
747 aStrOut
= aStrTable
+ " " + OUString::number( nTableStrNum
++ ) + ": ";
752 rStrm
.WriteOString( "<A NAME=\"table" )
753 .WriteOString( OString::number(nTab
) )
754 .WriteOString( "\">" );
755 TAG_ON( OOO_STRING_SVTOOLS_HTML_head1
);
757 TAG_ON( OOO_STRING_SVTOOLS_HTML_emphasis
);
759 pDoc
->GetName( nTab
, aStr
);
762 TAG_OFF( OOO_STRING_SVTOOLS_HTML_emphasis
);
763 TAG_OFF( OOO_STRING_SVTOOLS_HTML_head1
);
764 rStrm
.WriteOString( "</A>" ); OUT_LF();
769 nStartCol
= nStartColFix
;
770 nStartRow
= nStartRowFix
;
771 nEndCol
= nEndColFix
;
772 nEndRow
= nEndRowFix
;
773 if ( !TrimDataArea( nTab
, nStartCol
, nStartRow
, nEndCol
, nEndRow
) )
778 OStringBuffer
aByteStrOut(OOO_STRING_SVTOOLS_HTML_table
);
780 bTabHasGraphics
= bTabAlignedLeft
= false;
781 if ( bAll
&& pDrawLayer
)
782 PrepareGraphics( pDrawLayer
, nTab
, nStartCol
, nStartRow
,
786 if ( bTabAlignedLeft
)
788 aByteStrOut
.append(" " OOO_STRING_SVTOOLS_HTML_O_align
790 OOO_STRING_SVTOOLS_HTML_AL_left
"\"");
792 // ALIGN=LEFT allow text and graphics to flow around
794 aByteStrOut
.append(" " OOO_STRING_SVTOOLS_HTML_O_cellspacing
796 OString::number(nCellSpacing
) + "\"");
798 // BORDER=0, we do the styling of the cells in <TD>
799 aByteStrOut
.append(" " OOO_STRING_SVTOOLS_HTML_O_border
"=\"0\"");
800 IncIndent(1); TAG_ON_LF( aByteStrOut
.makeStringAndClear() );
802 // --- <COLGROUP> ----
804 SCCOL nCol
= nStartCol
;
805 sal_Int32 nWidth
= 0;
807 while( nCol
<= nEndCol
)
809 if( pDoc
->ColHidden(nCol
, nTab
) )
815 if( nWidth
!= ToPixel( pDoc
->GetColWidth( nCol
, nTab
) ) )
819 TAG_ON(lcl_getColGroupString(nSpan
, nWidth
));
820 TAG_OFF_LF( OOO_STRING_SVTOOLS_HTML_colgroup
);
822 nWidth
= ToPixel( pDoc
->GetColWidth( nCol
, nTab
) );
831 TAG_ON(lcl_getColGroupString(nSpan
, nWidth
));
832 TAG_OFF_LF( OOO_STRING_SVTOOLS_HTML_colgroup
);
836 // <TBODY> // Re-enable only when THEAD and TFOOT are exported
837 // IncIndent(1); TAG_ON_LF( OOO_STRING_SVTOOLS_HTML_tbody );
838 // At least old (3.x, 4.x?) Netscape doesn't follow <TABLE COLS=n> and
839 // <COL WIDTH=x> specified, but needs a width at every column.
840 bool bHasHiddenRows
= pDoc
->HasHiddenRows(nStartRow
, nEndRow
, nTab
);
841 // We need to cache sc::ColumnBlockPosition per each column.
842 std::vector
< sc::ColumnBlockPosition
> blockPos( nEndCol
- nStartCol
+ 1 );
843 for( SCCOL i
= nStartCol
; i
<= nEndCol
; ++i
)
844 pDoc
->InitColumnBlockPosition( blockPos
[ i
- nStartCol
], nTab
, i
);
845 for ( SCROW nRow
=nStartRow
; nRow
<=nEndRow
; nRow
++ )
847 if ( bHasHiddenRows
&& pDoc
->RowHidden(nRow
, nTab
) )
849 nRow
= pDoc
->FirstVisibleRow(nRow
+1, nEndRow
, nTab
);
854 IncIndent(1); TAG_ON_LF( OOO_STRING_SVTOOLS_HTML_tablerow
);
855 bTableDataHeight
= true; // height at every first cell of each row
856 for ( SCCOL nCol2
=nStartCol
; nCol2
<=nEndCol
; nCol2
++ )
858 if ( pDoc
->ColHidden(nCol2
, nTab
) )
861 if ( nCol2
== nEndCol
)
863 WriteCell( blockPos
[ nCol2
- nStartCol
], nCol2
, nRow
, nTab
);
864 bTableDataHeight
= false;
867 if ( nRow
== nEndRow
)
869 TAG_OFF_LF( OOO_STRING_SVTOOLS_HTML_tablerow
);
871 // TODO: Uncomment later
872 // IncIndent(-1); TAG_OFF_LF( OOO_STRING_SVTOOLS_HTML_tbody );
874 IncIndent(-1); TAG_OFF_LF( OOO_STRING_SVTOOLS_HTML_table
);
876 if ( bTabHasGraphics
&& !mbSkipImages
)
878 // the rest that is not in a cell
879 size_t ListSize
= aGraphList
.size();
880 for ( size_t i
= 0; i
< ListSize
; ++i
)
882 ScHTMLGraphEntry
* pE
= &aGraphList
[ i
];
884 WriteGraphEntry( pE
);
887 if ( bTabAlignedLeft
)
889 // clear <TABLE ALIGN=LEFT> with <BR CLEAR=LEFT>
891 OOO_STRING_SVTOOLS_HTML_linebreak
893 OOO_STRING_SVTOOLS_HTML_O_clear
"="
894 OOO_STRING_SVTOOLS_HTML_AL_left
);
895 TAG_ON_LF( aByteStrOut
.makeStringAndClear() );
900 OUT_COMMENT( u
"**************************************************************************" );
904 void ScHTMLExport::WriteCell( sc::ColumnBlockPosition
& rBlockPos
, SCCOL nCol
, SCROW nRow
, SCTAB nTab
)
906 std::optional
<Color
> aColorScale
;
907 ScAddress
aPos( nCol
, nRow
, nTab
);
908 ScRefCellValue
aCell(*pDoc
, aPos
, rBlockPos
);
909 const ScPatternAttr
* pAttr
= pDoc
->GetPattern( nCol
, nRow
, nTab
);
910 const SfxItemSet
* pCondItemSet
= pDoc
->GetCondResult( nCol
, nRow
, nTab
, &aCell
);
913 ScConditionalFormatList
* pCondList
= pDoc
->GetCondFormList(nTab
);
914 const ScCondFormatItem
& rCondItem
= pAttr
->GetItem(ATTR_CONDITIONAL
);
915 const ScCondFormatIndexes
& rCondIndex
= rCondItem
.GetCondFormatData();
916 if (rCondIndex
.size() > 0)
918 ScConditionalFormat
* pCondFmt
= pCondList
->GetFormat(rCondIndex
[0]);
921 const ScColorScaleFormat
* pEntry
= dynamic_cast<const ScColorScaleFormat
*>(pCondFmt
->GetEntry(0));
923 aColorScale
= pEntry
->GetColor(aPos
);
928 const ScMergeFlagAttr
& rMergeFlagAttr
= pAttr
->GetItem( ATTR_MERGE_FLAG
, pCondItemSet
);
929 if ( rMergeFlagAttr
.IsOverlapped() )
932 ScHTMLGraphEntry
* pGraphEntry
= nullptr;
933 if ( bTabHasGraphics
&& !mbSkipImages
)
935 size_t ListSize
= aGraphList
.size();
936 for ( size_t i
= 0; i
< ListSize
; ++i
)
938 ScHTMLGraphEntry
* pE
= &aGraphList
[ i
];
939 if ( pE
->bInCell
&& pE
->aRange
.Contains( aPos
) )
941 if ( pE
->aRange
.aStart
== aPos
)
947 return ; // Is a Col/RowSpan, Overlapped
952 sal_uInt32 nFormat
= pAttr
->GetNumberFormat( pFormatter
);
953 bool bValueData
= aCell
.hasNumeric();
954 SvtScriptType nScriptType
= SvtScriptType::NONE
;
955 if (!aCell
.isEmpty())
956 nScriptType
= pDoc
->GetScriptType(nCol
, nRow
, nTab
, &aCell
);
958 if ( nScriptType
== SvtScriptType::NONE
)
959 nScriptType
= aHTMLStyle
.nDefaultScriptType
;
961 OStringBuffer
aStrTD(OOO_STRING_SVTOOLS_HTML_tabledata
);
963 // border of the cells
964 const SvxBoxItem
* pBorder
= pDoc
->GetAttr( nCol
, nRow
, nTab
, ATTR_BORDER
);
965 if ( pBorder
&& (pBorder
->GetTop() || pBorder
->GetBottom() || pBorder
->GetLeft() || pBorder
->GetRight()) )
967 aStrTD
.append(" " OOO_STRING_SVTOOLS_HTML_style
"=\"");
969 bool bInsertSemicolon
= false;
970 aStrTD
.append(BorderToStyle("top", pBorder
->GetTop(),
972 aStrTD
.append(BorderToStyle("bottom", pBorder
->GetBottom(),
974 aStrTD
.append(BorderToStyle("left", pBorder
->GetLeft(),
976 aStrTD
.append(BorderToStyle("right", pBorder
->GetRight(),
983 sal_uInt16 nHeightPixel
;
985 const ScMergeAttr
& rMergeAttr
= pAttr
->GetItem( ATTR_MERGE
, pCondItemSet
);
986 if ( pGraphEntry
|| rMergeAttr
.IsMerged() )
992 nC
= std::max( SCCOL(pGraphEntry
->aRange
.aEnd
.Col() - nCol
+ 1),
993 rMergeAttr
.GetColMerge() );
995 nC
= rMergeAttr
.GetColMerge();
998 aStrTD
.append(" " OOO_STRING_SVTOOLS_HTML_O_colspan
999 "=" + OString::number(static_cast<sal_Int32
>(nC
)));
1001 for ( jC
=nCol
, v
=0; jC
<nC
; jC
++ )
1002 v
+= pDoc
->GetColWidth( jC
, nTab
);
1006 nR
= std::max( SCROW(pGraphEntry
->aRange
.aEnd
.Row() - nRow
+ 1),
1007 rMergeAttr
.GetRowMerge() );
1009 nR
= rMergeAttr
.GetRowMerge();
1012 aStrTD
.append(" " OOO_STRING_SVTOOLS_HTML_O_rowspan
1013 "=" + OString::number(static_cast<sal_Int32
>(nR
)));
1015 v
= pDoc
->GetRowHeight( nRow
, nR
-1, nTab
);
1016 nHeightPixel
= ToPixel( static_cast< sal_uInt16
>( v
) );
1019 nHeightPixel
= ToPixel( pDoc
->GetRowHeight( nRow
, nTab
) );
1022 nHeightPixel
= ToPixel( pDoc
->GetRowHeight( nRow
, nTab
) );
1024 if ( bTableDataHeight
)
1026 aStrTD
.append(" " OOO_STRING_SVTOOLS_HTML_O_height
"=\"" +
1027 OString::number(nHeightPixel
) + "\"");
1030 const SvxFontItem
& rFontItem
= static_cast<const SvxFontItem
&>( pAttr
->GetItem(
1031 ScGlobal::GetScriptedWhichID( nScriptType
, ATTR_FONT
),
1034 const SvxFontHeightItem
& rFontHeightItem
= static_cast<const SvxFontHeightItem
&>(
1035 pAttr
->GetItem( ScGlobal::GetScriptedWhichID( nScriptType
,
1036 ATTR_FONT_HEIGHT
), pCondItemSet
) );
1038 const SvxWeightItem
& rWeightItem
= static_cast<const SvxWeightItem
&>( pAttr
->GetItem(
1039 ScGlobal::GetScriptedWhichID( nScriptType
, ATTR_FONT_WEIGHT
),
1042 const SvxPostureItem
& rPostureItem
= static_cast<const SvxPostureItem
&>(
1043 pAttr
->GetItem( ScGlobal::GetScriptedWhichID( nScriptType
,
1044 ATTR_FONT_POSTURE
), pCondItemSet
) );
1046 const SvxUnderlineItem
& rUnderlineItem
=
1047 pAttr
->GetItem( ATTR_FONT_UNDERLINE
, pCondItemSet
);
1049 const SvxCrossedOutItem
& rCrossedOutItem
=
1050 pAttr
->GetItem( ATTR_FONT_CROSSEDOUT
, pCondItemSet
);
1052 const SvxColorItem
& rColorItem
= pAttr
->GetItem(
1053 ATTR_FONT_COLOR
, pCondItemSet
);
1055 const SvxHorJustifyItem
& rHorJustifyItem
=
1056 pAttr
->GetItem( ATTR_HOR_JUSTIFY
, pCondItemSet
);
1058 const SvxVerJustifyItem
& rVerJustifyItem
=
1059 pAttr
->GetItem( ATTR_VER_JUSTIFY
, pCondItemSet
);
1061 const SvxBrushItem
& rBrushItem
= pAttr
->GetItem(
1062 ATTR_BACKGROUND
, pCondItemSet
);
1066 aBgColor
= *aColorScale
;
1067 else if ( rBrushItem
.GetColor().GetAlpha() == 0 )
1068 aBgColor
= aHTMLStyle
.aBackgroundColor
; // No unwanted background color
1070 aBgColor
= rBrushItem
.GetColor();
1072 bool bBold
= ( WEIGHT_BOLD
<= rWeightItem
.GetWeight() );
1073 bool bItalic
= ( ITALIC_NONE
!= rPostureItem
.GetPosture() );
1074 bool bUnderline
= ( LINESTYLE_NONE
!= rUnderlineItem
.GetLineStyle() );
1075 bool bCrossedOut
= ( STRIKEOUT_SINGLE
<= rCrossedOutItem
.GetStrikeout() );
1076 bool bSetFontColor
= ( COL_AUTO
!= rColorItem
.GetValue() ); // default is AUTO now
1077 bool bSetFontName
= ( aHTMLStyle
.aFontFamilyName
!= rFontItem
.GetFamilyName() );
1078 sal_uInt16 nSetFontSizeNumber
= 0;
1079 sal_uInt32 nFontHeight
= rFontHeightItem
.GetHeight();
1080 if ( nFontHeight
!= aHTMLStyle
.nFontHeight
)
1082 nSetFontSizeNumber
= GetFontSizeNumber( static_cast<sal_uInt16
>(nFontHeight
) );
1083 if ( nSetFontSizeNumber
== aHTMLStyle
.nFontSizeNumber
)
1084 nSetFontSizeNumber
= 0; // no difference, don't set
1087 bool bSetFont
= (bSetFontColor
|| bSetFontName
|| nSetFontSizeNumber
);
1089 //! TODO: we could entirely use CSS1 here instead, but that would exclude
1090 //! Netscape 3.0 and Netscape 4.x without JavaScript enabled.
1091 //! Do we want that?
1093 switch( rHorJustifyItem
.GetValue() )
1095 case SvxCellHorJustify::Standard
:
1096 pChar
= (bValueData
? OOO_STRING_SVTOOLS_HTML_AL_right
: OOO_STRING_SVTOOLS_HTML_AL_left
);
1098 case SvxCellHorJustify::Center
: pChar
= OOO_STRING_SVTOOLS_HTML_AL_center
; break;
1099 case SvxCellHorJustify::Block
: pChar
= OOO_STRING_SVTOOLS_HTML_AL_justify
; break;
1100 case SvxCellHorJustify::Right
: pChar
= OOO_STRING_SVTOOLS_HTML_AL_right
; break;
1101 case SvxCellHorJustify::Left
:
1102 case SvxCellHorJustify::Repeat
:
1103 default: pChar
= OOO_STRING_SVTOOLS_HTML_AL_left
; break;
1106 aStrTD
.append(" " OOO_STRING_SVTOOLS_HTML_O_align
"=\"" +
1107 OString::Concat(pChar
) + "\"");
1109 switch( rVerJustifyItem
.GetValue() )
1111 case SvxCellVerJustify::Top
: pChar
= OOO_STRING_SVTOOLS_HTML_VA_top
; break;
1112 case SvxCellVerJustify::Center
: pChar
= OOO_STRING_SVTOOLS_HTML_VA_middle
; break;
1113 case SvxCellVerJustify::Bottom
: pChar
= OOO_STRING_SVTOOLS_HTML_VA_bottom
; break;
1114 case SvxCellVerJustify::Standard
:
1115 default: pChar
= nullptr;
1119 aStrTD
.append(OString::Concat(" " OOO_STRING_SVTOOLS_HTML_O_valign
"=") + pChar
);
1122 if ( aHTMLStyle
.aBackgroundColor
!= aBgColor
)
1124 aStrTD
.append(" " OOO_STRING_SVTOOLS_HTML_O_bgcolor
"="
1125 + lcl_makeHTMLColorTriplet(aBgColor
));
1131 switch (aCell
.getType())
1133 case CELLTYPE_VALUE
:
1134 fVal
= aCell
.getDouble();
1135 if ( bCalcAsShown
&& fVal
!= 0.0 )
1136 fVal
= pDoc
->RoundValueAsShown( fVal
, nFormat
);
1138 case CELLTYPE_FORMULA
:
1139 fVal
= aCell
.getFormula()->GetValue();
1142 OSL_FAIL( "value data with unsupported cell type" );
1146 aStrTD
.append(HTMLOutFuncs::CreateTableDataOptionsValNum(bValueData
, fVal
,
1147 nFormat
, *pFormatter
, &aNonConvertibleChars
));
1149 std::optional
<tools::JsonWriter
> oJson
;
1150 const SvNumberformat
* pNumberFormat
= nullptr;
1155 const SvNumberformat
* pFormatEntry
= pFormatter
->GetEntry(nFormat
);
1158 OUString aNumStr
= pFormatEntry
->GetFormatstring();
1159 if (aNumStr
== "BOOLEAN")
1163 oJson
->put("1", static_cast<sal_Int32
>(4));
1164 oJson
->put("4", static_cast<sal_Int32
>(fVal
));
1170 oJson
->put("1", static_cast<sal_Int32
>(3));
1171 oJson
->put("3", static_cast<sal_Int32
>(fVal
));
1172 pNumberFormat
= pFormatEntry
;
1177 if (aCell
.getType() == CELLTYPE_FORMULA
)
1179 // If it's a formula, then also emit that, grammar is R1C1 reference style.
1180 OUString aFormula
= aCell
.getFormula()->GetFormula(
1181 formula::FormulaGrammar::GRAM_ENGLISH_XL_R1C1
);
1182 aStrTD
.append(" " OOO_STRING_SVTOOLS_HTML_O_DSformula
"=\""
1183 + HTMLOutFuncs::ConvertStringToHTML(aFormula
) + "\"");
1190 oJson
->put("1", static_cast<sal_Int32
>(2));
1191 oJson
->put("2", pDoc
->GetString(aPos
));
1196 OUString aJsonString
= OUString::fromUtf8(oJson
->finishAndGetAsOString());
1197 aStrTD
.append(" " OOO_STRING_SVTOOLS_HTML_O_DSval
"=\""
1198 + HTMLOutFuncs::ConvertStringToHTML(aJsonString
) + "\"");
1203 // 2 is a number format.
1205 oJson
->put("1", static_cast<sal_Int32
>(2));
1206 oJson
->put("2", pNumberFormat
->GetFormatstring());
1207 // The number format is for a number.
1208 oJson
->put("3", static_cast<sal_Int32
>(1));
1209 OUString aJsonString
= OUString::fromUtf8(oJson
->finishAndGetAsOString());
1210 aStrTD
.append(" " OOO_STRING_SVTOOLS_HTML_O_DSnum
"=\""
1211 + HTMLOutFuncs::ConvertStringToHTML(aJsonString
) + "\"");
1214 TAG_ON(aStrTD
.makeStringAndClear());
1216 //write the note for this as the first thing in the tag
1217 ScPostIt
* pNote
= pDoc
->HasNote(aPos
) ? pDoc
->GetNote(aPos
) : nullptr;
1220 //create the comment indicator
1221 OString aStr
= OOO_STRING_SVTOOLS_HTML_anchor
" "
1222 OOO_STRING_SVTOOLS_HTML_O_class
"=\"comment-indicator\""_ostr
;
1224 TAG_OFF(OOO_STRING_SVTOOLS_HTML_anchor
);
1227 //create the element holding the contents
1228 //this is a bit naive, since it doesn't separate
1229 //lines into html breaklines yet
1230 TAG_ON(OOO_STRING_SVTOOLS_HTML_comment2
);
1231 OUT_STR( pNote
->GetText() );
1232 TAG_OFF(OOO_STRING_SVTOOLS_HTML_comment2
);
1236 if ( bBold
) TAG_ON( OOO_STRING_SVTOOLS_HTML_bold
);
1237 if ( bItalic
) TAG_ON( OOO_STRING_SVTOOLS_HTML_italic
);
1238 if ( bUnderline
) TAG_ON( OOO_STRING_SVTOOLS_HTML_underline
);
1239 if ( bCrossedOut
) TAG_ON( OOO_STRING_SVTOOLS_HTML_strikethrough
);
1243 OStringBuffer
aStr(OOO_STRING_SVTOOLS_HTML_font
);
1246 aStr
.append(" " OOO_STRING_SVTOOLS_HTML_O_face
"=\"");
1248 if (!rFontItem
.GetFamilyName().isEmpty())
1250 const OUString
& rList
= rFontItem
.GetFamilyName();
1251 for (sal_Int32 nPos
{0};;)
1253 OString aTmpStr
= HTMLOutFuncs::ConvertStringToHTML(
1254 o3tl::getToken( rList
, 0, ';', nPos
),
1255 &aNonConvertibleChars
);
1256 aStr
.append(aTmpStr
);
1265 if ( nSetFontSizeNumber
)
1267 aStr
.append(" " OOO_STRING_SVTOOLS_HTML_O_size
"="
1268 + OString::number(static_cast<sal_Int32
>(nSetFontSizeNumber
)));
1270 if ( bSetFontColor
)
1272 Color aColor
= rColorItem
.GetValue();
1274 // always export automatic text color as black
1275 if ( aColor
== COL_AUTO
)
1278 aStr
.append(" " OOO_STRING_SVTOOLS_HTML_O_color
"="
1279 + lcl_makeHTMLColorTriplet(aColor
));
1281 TAG_ON(aStr
.makeStringAndClear());
1285 bool bWriteHyperLink(false);
1286 if (aCell
.getType() == CELLTYPE_FORMULA
)
1288 ScFormulaCell
* pFCell
= aCell
.getFormula();
1289 if (pFCell
->IsHyperLinkCell())
1292 pFCell
->GetURLResult(aURL
, aCellText
);
1293 bWriteHyperLink
= true;
1297 if (bWriteHyperLink
)
1299 OString aURLStr
= HTMLOutFuncs::ConvertStringToHTML(aURL
, &aNonConvertibleChars
);
1300 OString aStr
= OOO_STRING_SVTOOLS_HTML_anchor
" " OOO_STRING_SVTOOLS_HTML_O_href
"=\"" + aURLStr
+ "\"";
1305 bool bFieldText
= false;
1307 const Color
* pColor
;
1308 switch (aCell
.getType())
1310 case CELLTYPE_EDIT
:
1311 bFieldText
= WriteFieldText(aCell
.getEditText());
1316 aStrOut
= ScCellFormat::GetString(aCell
, nFormat
, &pColor
, nullptr, *pDoc
);
1321 if ( aStrOut
.isEmpty() )
1323 TAG_ON( OOO_STRING_SVTOOLS_HTML_linebreak
); // No completely empty line
1327 sal_Int32 nPos
= aStrOut
.indexOf( '\n' );
1334 sal_Int32 nStartPos
= 0;
1337 OUString aSingleLine
= aStrOut
.copy( nStartPos
, nPos
- nStartPos
);
1338 OUT_STR( aSingleLine
);
1339 TAG_ON( OOO_STRING_SVTOOLS_HTML_linebreak
);
1340 nStartPos
= nPos
+ 1;
1342 while( ( nPos
= aStrOut
.indexOf( '\n', nStartPos
) ) != -1 );
1343 OUString aSingleLine
= aStrOut
.copy( nStartPos
);
1344 OUT_STR( aSingleLine
);
1349 WriteGraphEntry( pGraphEntry
);
1351 if (bWriteHyperLink
) { TAG_OFF(OOO_STRING_SVTOOLS_HTML_anchor
); }
1353 if ( bSetFont
) TAG_OFF( OOO_STRING_SVTOOLS_HTML_font
);
1354 if ( bCrossedOut
) TAG_OFF( OOO_STRING_SVTOOLS_HTML_strikethrough
);
1355 if ( bUnderline
) TAG_OFF( OOO_STRING_SVTOOLS_HTML_underline
);
1356 if ( bItalic
) TAG_OFF( OOO_STRING_SVTOOLS_HTML_italic
);
1357 if ( bBold
) TAG_OFF( OOO_STRING_SVTOOLS_HTML_bold
);
1359 TAG_OFF_LF( OOO_STRING_SVTOOLS_HTML_tabledata
);
1362 bool ScHTMLExport::WriteFieldText( const EditTextObject
* pData
)
1364 bool bFields
= false;
1365 // text and anchor of URL fields, Doc-Engine is a ScFieldEditEngine
1366 EditEngine
& rEngine
= pDoc
->GetEditEngine();
1367 rEngine
.SetText( *pData
);
1368 sal_Int32 nParas
= rEngine
.GetParagraphCount();
1371 ESelection
aSel( 0, 0, nParas
-1, rEngine
.GetTextLen( nParas
-1 ) );
1372 SfxItemSet
aSet( rEngine
.GetAttribs( aSel
) );
1373 SfxItemState eFieldState
= aSet
.GetItemState( EE_FEATURE_FIELD
, false );
1374 if ( eFieldState
== SfxItemState::INVALID
|| eFieldState
== SfxItemState::SET
)
1379 bool bOldUpdateMode
= rEngine
.SetUpdateLayout( true ); // no portions if not formatted
1380 for ( sal_Int32 nPar
=0; nPar
< nParas
; nPar
++ )
1383 TAG_ON( OOO_STRING_SVTOOLS_HTML_linebreak
);
1384 std::vector
<sal_Int32
> aPortions
;
1385 rEngine
.GetPortions( nPar
, aPortions
);
1386 sal_Int32 nStart
= 0;
1387 for ( const sal_Int32 nEnd
: aPortions
)
1389 ESelection
aSel( nPar
, nStart
, nPar
, nEnd
);
1391 // fields are single characters
1392 if ( nEnd
== nStart
+1 )
1394 SfxItemSet aSet
= rEngine
.GetAttribs( aSel
);
1395 if ( const SvxFieldItem
* pFieldItem
= aSet
.GetItemIfSet( EE_FEATURE_FIELD
, false ) )
1397 const SvxFieldData
* pField
= pFieldItem
->GetField();
1398 if (const SvxURLField
* pURLField
= dynamic_cast<const SvxURLField
*>(pField
))
1401 rStrm
.WriteChar( '<' ).WriteOString( OOO_STRING_SVTOOLS_HTML_anchor
).WriteChar( ' ' ).WriteOString( OOO_STRING_SVTOOLS_HTML_O_href
).WriteOString( "=\"" );
1402 OUT_STR( pURLField
->GetURL() );
1403 rStrm
.WriteOString( "\">" );
1404 OUT_STR( pURLField
->GetRepresentation() );
1405 rStrm
.WriteOString( "</" ).WriteOString( OOO_STRING_SVTOOLS_HTML_anchor
).WriteChar( '>' );
1410 OUT_STR( rEngine
.GetText( aSel
) );
1414 rEngine
.SetUpdateLayout( bOldUpdateMode
);
1419 void ScHTMLExport::CopyLocalFileToINet( OUString
& rFileNm
,
1420 std::u16string_view rTargetNm
)
1422 INetURLObject aFileUrl
, aTargetUrl
;
1423 aFileUrl
.SetSmartURL( rFileNm
);
1424 aTargetUrl
.SetSmartURL( rTargetNm
);
1425 if (!(INetProtocol::File
== aFileUrl
.GetProtocol()
1426 && (INetProtocol::Http
== aTargetUrl
.GetProtocol()
1427 || INetProtocol::Https
== aTargetUrl
.GetProtocol()
1428 || INetProtocol::VndSunStarWebdav
== aTargetUrl
.GetProtocol()
1429 || INetProtocol::Smb
== aTargetUrl
.GetProtocol()
1430 || INetProtocol::Sftp
== aTargetUrl
.GetProtocol()
1431 || INetProtocol::Cmis
== aTargetUrl
.GetProtocol())))
1438 // Did we already move the file?
1439 std::map
<OUString
, OUString
>::iterator it
= pFileNameMap
->find( rFileNm
);
1440 if( it
!= pFileNameMap
->end() )
1442 rFileNm
= it
->second
;
1448 pFileNameMap
.reset( new std::map
<OUString
, OUString
> );
1452 SvFileStream
aTmp( aFileUrl
.PathToFileName(), StreamMode::READ
);
1454 OUString aSrc
= rFileNm
;
1455 OUString aDest
= aTargetUrl
.GetPartBeforeLastName() + aFileUrl
.GetLastName();
1457 SfxMedium
aMedium( aDest
, StreamMode::WRITE
| StreamMode::SHARE_DENYNONE
);
1460 SvFileStream
aCpy( aMedium
.GetPhysicalName(), StreamMode::WRITE
);
1461 aCpy
.WriteStream( aTmp
);
1468 bRet
= ERRCODE_NONE
== aMedium
.GetErrorIgnoreWarning();
1472 pFileNameMap
->insert( std::make_pair( aSrc
, aDest
) );
1477 void ScHTMLExport::IncIndent( short nVal
)
1479 sIndent
[nIndent
] = '\t';
1480 nIndent
= nIndent
+ nVal
;
1483 else if ( nIndent
> nIndentMax
)
1484 nIndent
= nIndentMax
;
1485 sIndent
[nIndent
] = 0;
1488 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */