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>
54 #include <htmlexp.hxx>
57 #include <document.hxx>
59 #include <patattr.hxx>
60 #include <stlpool.hxx>
61 #include <scresid.hxx>
62 #include <formulacell.hxx>
63 #include <cellform.hxx>
64 #include <docoptio.hxx>
65 #include <editutil.hxx>
67 #include <cellvalue.hxx>
68 #include <mtvelements.hxx>
70 #include <editeng/flditem.hxx>
71 #include <editeng/borderline.hxx>
73 // Without strings.hrc: error C2679: binary '=' : no operator defined which takes a
74 // right-hand operand of type 'const class String (__stdcall *)(class ScResId)'
76 // const String aStrTable( ScResId( SCSTR_TABLE ) ); aStrOut = aStrTable;
78 #include <strings.hrc>
79 #include <globstr.hrc>
81 #include <com/sun/star/frame/XModel.hpp>
82 #include <com/sun/star/uno/Reference.h>
83 #include <com/sun/star/document/XDocumentProperties.hpp>
84 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
85 #include <rtl/strbuf.hxx>
86 #include <officecfg/Office/Common.hxx>
88 using ::editeng::SvxBorderLine
;
89 using namespace ::com::sun::star
;
91 const char sMyBegComment
[] = "<!-- ";
92 const char sMyEndComment
[] = " -->";
93 const char sDisplay
[] = "display:";
94 const char sBorder
[] = "border:";
95 const char sBackground
[] = "background:";
97 const sal_uInt16
ScHTMLExport::nDefaultFontSize
[SC_HTML_FONTSIZES
] =
99 HTMLFONTSZ1_DFLT
, HTMLFONTSZ2_DFLT
, HTMLFONTSZ3_DFLT
, HTMLFONTSZ4_DFLT
,
100 HTMLFONTSZ5_DFLT
, HTMLFONTSZ6_DFLT
, HTMLFONTSZ7_DFLT
103 sal_uInt16
ScHTMLExport::nFontSize
[SC_HTML_FONTSIZES
] = { 0 };
105 const char* ScHTMLExport::pFontSizeCss
[SC_HTML_FONTSIZES
] =
107 "xx-small", "x-small", "small", "medium", "large", "x-large", "xx-large"
110 const sal_uInt16
ScHTMLExport::nCellSpacing
= 0;
111 const char ScHTMLExport::sIndentSource
[nIndentMax
+1] =
112 "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t";
114 // Macros for HTML export
116 #define TAG_ON( tag ) HTMLOutFuncs::Out_AsciiTag( rStrm, tag )
117 #define TAG_OFF( tag ) HTMLOutFuncs::Out_AsciiTag( rStrm, tag, false )
118 #define OUT_STR( str ) HTMLOutFuncs::Out_String( rStrm, str, &aNonConvertibleChars )
119 #define OUT_LF() rStrm.WriteCharPtr( SAL_NEWLINE_STRING ).WriteCharPtr( GetIndentStr() )
120 #define TAG_ON_LF( tag ) (TAG_ON( tag ).WriteCharPtr( SAL_NEWLINE_STRING ).WriteCharPtr( GetIndentStr() ))
121 #define TAG_OFF_LF( tag ) (TAG_OFF( tag ).WriteCharPtr( SAL_NEWLINE_STRING ).WriteCharPtr( GetIndentStr() ))
122 #define OUT_HR() TAG_ON_LF( OOO_STRING_SVTOOLS_HTML_horzrule )
123 #define OUT_COMMENT( comment ) (rStrm.WriteCharPtr( sMyBegComment ), OUT_STR( comment ) \
124 .WriteCharPtr( sMyEndComment ).WriteCharPtr( SAL_NEWLINE_STRING ) \
125 .WriteCharPtr( GetIndentStr() ))
127 #define OUT_SP_CSTR_ASS( s ) rStrm.WriteChar( ' ').WriteCharPtr( s ).WriteChar( '=' )
129 #define GLOBSTR(id) ScResId( id )
131 void ScFormatFilterPluginImpl::ScExportHTML( SvStream
& rStrm
, const OUString
& rBaseURL
, ScDocument
* pDoc
,
132 const ScRange
& rRange
, const rtl_TextEncoding
/*eNach*/, bool bAll
,
133 const OUString
& rStreamPath
, OUString
& rNonConvertibleChars
, const OUString
& rFilterOptions
)
135 ScHTMLExport
aEx( rStrm
, rBaseURL
, pDoc
, rRange
, bAll
, rStreamPath
, rFilterOptions
);
137 rNonConvertibleChars
= aEx
.GetNonConvertibleChars();
140 static OString
lcl_getColGroupString(sal_Int32 nSpan
, sal_Int32 nWidth
)
142 OStringBuffer
aByteStr(OOO_STRING_SVTOOLS_HTML_colgroup
);
143 aByteStr
.append(' ');
146 aByteStr
.append(OOO_STRING_SVTOOLS_HTML_O_span
);
147 aByteStr
.append("=\"");
148 aByteStr
.append(nSpan
);
149 aByteStr
.append("\" ");
151 aByteStr
.append(OOO_STRING_SVTOOLS_HTML_O_width
);
152 aByteStr
.append("=\"");
153 aByteStr
.append(nWidth
);
154 aByteStr
.append('"');
155 return aByteStr
.makeStringAndClear();
158 static void lcl_AddStamp( OUString
& rStr
, std::u16string_view rName
,
159 const css::util::DateTime
& rDateTime
,
160 const LocaleDataWrapper
& rLoc
)
162 Date
aD(rDateTime
.Day
, rDateTime
.Month
, rDateTime
.Year
);
163 tools::Time
aT(rDateTime
.Hours
, rDateTime
.Minutes
, rDateTime
.Seconds
,
164 rDateTime
.NanoSeconds
);
165 DateTime
aDateTime(aD
,aT
);
167 OUString aStrDate
= rLoc
.getDate( aDateTime
);
168 OUString aStrTime
= rLoc
.getTime( aDateTime
);
170 rStr
+= GLOBSTR( STR_BY
) + " ";
175 rStr
+= " " + GLOBSTR( STR_ON
) + " ";
176 if (!aStrDate
.isEmpty())
181 if (!aStrTime
.isEmpty())
187 static OString
lcl_makeHTMLColorTriplet(const Color
& rColor
)
191 // <font COLOR="#00FF40">hello</font>
192 snprintf( buf
, 24, "\"#%02X%02X%02X\"", rColor
.GetRed(), rColor
.GetGreen(), rColor
.GetBlue() );
197 ScHTMLExport::ScHTMLExport( SvStream
& rStrmP
, OUString _aBaseURL
, ScDocument
* pDocP
,
198 const ScRange
& rRangeP
, bool bAllP
,
199 OUString aStreamPathP
, std::u16string_view rFilterOptions
) :
200 ScExportBase( rStrmP
, pDocP
, rRangeP
),
201 aBaseURL(std::move( _aBaseURL
)),
202 aStreamPath(std::move( aStreamPathP
)),
203 pAppWin( Application::GetDefaultDevice() ),
207 bTabHasGraphics( false ),
208 bTabAlignedLeft( false ),
209 bCalcAsShown( pDocP
->GetDocOptions().IsCalcAsShown() ),
210 bTableDataHeight( true ),
211 mbSkipImages ( false ),
212 mbSkipHeaderFooter( false )
214 strcpy( sIndent
, sIndentSource
);
217 // set HTML configuration
218 bCopyLocalFileToINet
= officecfg::Office::Common::Filter::HTML::Export::LocalGraphic::get();
220 if (rFilterOptions
== u
"SkipImages")
224 else if (rFilterOptions
== u
"SkipHeaderFooter")
226 mbSkipHeaderFooter
= true;
229 for ( sal_uInt16 j
=0; j
< SC_HTML_FONTSIZES
; j
++ )
231 sal_uInt16 nSize
= SvxHtmlOptions::GetFontSize( j
);
232 // remember in Twips, like our SvxFontHeightItem
234 nFontSize
[j
] = nSize
* 20;
236 nFontSize
[j
] = nDefaultFontSize
[j
] * 20;
239 const SCTAB nCount
= pDoc
->GetTableCount();
240 for ( SCTAB nTab
= 0; nTab
< nCount
; nTab
++ )
242 if ( !IsEmptyTable( nTab
) )
247 ScHTMLExport::~ScHTMLExport()
252 sal_uInt16
ScHTMLExport::GetFontSizeNumber( sal_uInt16 nHeight
)
254 sal_uInt16 nSize
= 1;
255 for ( sal_uInt16 j
=SC_HTML_FONTSIZES
-1; j
>0; j
-- )
257 if( nHeight
> (nFontSize
[j
] + nFontSize
[j
-1]) / 2 )
258 { // The one next to it
266 const char* ScHTMLExport::GetFontSizeCss( sal_uInt16 nHeight
)
268 sal_uInt16 nSize
= GetFontSizeNumber( nHeight
);
269 return pFontSizeCss
[ nSize
-1 ];
272 sal_uInt16
ScHTMLExport::ToPixel( sal_uInt16 nVal
)
276 nVal
= static_cast<sal_uInt16
>(pAppWin
->LogicToPixel(
277 Size( nVal
, nVal
), MapMode( MapUnit::MapTwip
) ).Width());
278 if( !nVal
) // If there's a Twip there should also be a Pixel
284 Size
ScHTMLExport::MMToPixel( const Size
& rSize
)
286 Size aSize
= pAppWin
->LogicToPixel( rSize
, MapMode( MapUnit::Map100thMM
) );
287 // If there's something there should also be a Pixel
288 if ( !aSize
.Width() && rSize
.Width() )
290 if ( !aSize
.Height() && rSize
.Height() )
291 aSize
.setHeight( 1 );
295 void ScHTMLExport::Write()
297 if (!mbSkipHeaderFooter
)
299 rStrm
.WriteChar( '<' ).WriteCharPtr( OOO_STRING_SVTOOLS_HTML_doctype
).WriteChar( ' ' ).WriteCharPtr( OOO_STRING_SVTOOLS_HTML_doctype5
).WriteChar( '>' )
300 .WriteCharPtr( SAL_NEWLINE_STRING
).WriteCharPtr( SAL_NEWLINE_STRING
);
301 TAG_ON_LF( OOO_STRING_SVTOOLS_HTML_html
);
307 if (!mbSkipHeaderFooter
)
308 TAG_OFF_LF( OOO_STRING_SVTOOLS_HTML_html
);
311 void ScHTMLExport::WriteHeader()
313 IncIndent(1); TAG_ON_LF( OOO_STRING_SVTOOLS_HTML_head
);
315 if ( pDoc
->IsClipOrUndo() )
316 { // no real DocInfo available, but some META information like charset needed
317 SfxFrameHTMLWriter::Out_DocInfo( rStrm
, aBaseURL
, nullptr, sIndent
, &aNonConvertibleChars
);
321 uno::Reference
<document::XDocumentPropertiesSupplier
> xDPS(
322 pDoc
->GetDocumentShell()->GetModel(), uno::UNO_QUERY_THROW
);
323 uno::Reference
<document::XDocumentProperties
> xDocProps
324 = xDPS
->getDocumentProperties();
325 SfxFrameHTMLWriter::Out_DocInfo( rStrm
, aBaseURL
, xDocProps
,
326 sIndent
, &aNonConvertibleChars
);
329 if (!xDocProps
->getPrintedBy().isEmpty())
331 OUT_COMMENT( GLOBSTR( STR_DOC_INFO
) );
332 OUString aStrOut
= GLOBSTR( STR_DOC_PRINTED
) + ": ";
333 lcl_AddStamp( aStrOut
, xDocProps
->getPrintedBy(),
334 xDocProps
->getPrintDate(), ScGlobal::getLocaleData() );
335 OUT_COMMENT( aStrOut
);
342 PageDefaults( bAll
? 0 : aRange
.aStart
.Tab() );
344 rStrm
.WriteCharPtr( "<" ).WriteCharPtr( OOO_STRING_SVTOOLS_HTML_style
).WriteCharPtr( " " ).WriteCharPtr( OOO_STRING_SVTOOLS_HTML_O_type
).WriteCharPtr( "=\"text/css\">" );
347 rStrm
.WriteCharPtr(OOO_STRING_SVTOOLS_HTML_body
);
348 rStrm
.WriteCharPtr(",");
349 rStrm
.WriteCharPtr(OOO_STRING_SVTOOLS_HTML_division
);
350 rStrm
.WriteCharPtr(",");
351 rStrm
.WriteCharPtr(OOO_STRING_SVTOOLS_HTML_table
);
352 rStrm
.WriteCharPtr(",");
353 rStrm
.WriteCharPtr(OOO_STRING_SVTOOLS_HTML_thead
);
354 rStrm
.WriteCharPtr(",");
355 rStrm
.WriteCharPtr(OOO_STRING_SVTOOLS_HTML_tbody
);
356 rStrm
.WriteCharPtr(",");
357 rStrm
.WriteCharPtr(OOO_STRING_SVTOOLS_HTML_tfoot
);
358 rStrm
.WriteCharPtr(",");
359 rStrm
.WriteCharPtr(OOO_STRING_SVTOOLS_HTML_tablerow
);
360 rStrm
.WriteCharPtr(",");
361 rStrm
.WriteCharPtr(OOO_STRING_SVTOOLS_HTML_tableheader
);
362 rStrm
.WriteCharPtr(",");
363 rStrm
.WriteCharPtr(OOO_STRING_SVTOOLS_HTML_tabledata
);
364 rStrm
.WriteCharPtr(",");
365 rStrm
.WriteCharPtr(OOO_STRING_SVTOOLS_HTML_parabreak
);
366 rStrm
.WriteCharPtr(" { ");
367 rStrm
.WriteCharPtr("font-family:");
369 if (!aHTMLStyle
.aFontFamilyName
.isEmpty())
371 const OUString
& rList
= aHTMLStyle
.aFontFamilyName
;
372 for(sal_Int32 nPos
{0};;)
374 rStrm
.WriteChar( '\"' );
375 OUT_STR( rList
.getToken( 0, ';', nPos
) );
376 rStrm
.WriteChar( '\"' );
379 rStrm
.WriteCharPtr( ", " );
382 rStrm
.WriteCharPtr("; ");
383 rStrm
.WriteCharPtr("font-size:");
384 rStrm
.WriteCharPtr(GetFontSizeCss(static_cast<sal_uInt16
>(aHTMLStyle
.nFontHeight
)));
385 rStrm
.WriteCharPtr(" }");
389 // write the style for the comments to make them stand out from normal cell content
390 // this is done through only showing the cell contents when the custom indicator is hovered
391 rStrm
.WriteCharPtr(OOO_STRING_SVTOOLS_HTML_anchor
);
392 rStrm
.WriteCharPtr(".comment-indicator:hover");
393 rStrm
.WriteCharPtr(" + ");
394 rStrm
.WriteCharPtr(OOO_STRING_SVTOOLS_HTML_comment2
);
395 rStrm
.WriteCharPtr(" { ");
396 rStrm
.WriteCharPtr(sBackground
);
397 rStrm
.WriteCharPtr("#ffd");
398 rStrm
.WriteCharPtr("; ");
399 rStrm
.WriteCharPtr("position:");
400 rStrm
.WriteCharPtr("absolute");
401 rStrm
.WriteCharPtr("; ");
402 rStrm
.WriteCharPtr(sDisplay
);
403 rStrm
.WriteCharPtr("block");
404 rStrm
.WriteCharPtr("; ");
405 rStrm
.WriteCharPtr(sBorder
);
406 rStrm
.WriteCharPtr("1px solid black");
407 rStrm
.WriteCharPtr("; ");
408 rStrm
.WriteCharPtr("padding:");
409 rStrm
.WriteCharPtr("0.5em");
410 rStrm
.WriteCharPtr("; ");
411 rStrm
.WriteCharPtr(" } ");
415 rStrm
.WriteCharPtr(OOO_STRING_SVTOOLS_HTML_anchor
);
416 rStrm
.WriteCharPtr(".comment-indicator");
417 rStrm
.WriteCharPtr(" { ");
418 rStrm
.WriteCharPtr(sBackground
);
419 rStrm
.WriteCharPtr("red");
420 rStrm
.WriteCharPtr("; ");
421 rStrm
.WriteCharPtr(sDisplay
);
422 rStrm
.WriteCharPtr("inline-block");
423 rStrm
.WriteCharPtr("; ");
424 rStrm
.WriteCharPtr(sBorder
);
425 rStrm
.WriteCharPtr("1px solid black");
426 rStrm
.WriteCharPtr("; ");
427 rStrm
.WriteCharPtr("width:");
428 rStrm
.WriteCharPtr("0.5em");
429 rStrm
.WriteCharPtr("; ");
430 rStrm
.WriteCharPtr("height:");
431 rStrm
.WriteCharPtr("0.5em");
432 rStrm
.WriteCharPtr("; ");
433 rStrm
.WriteCharPtr(" } ");
437 rStrm
.WriteCharPtr(OOO_STRING_SVTOOLS_HTML_comment2
);
438 rStrm
.WriteCharPtr(" { ");
439 rStrm
.WriteCharPtr(sDisplay
);
440 rStrm
.WriteCharPtr("none");
441 rStrm
.WriteCharPtr("; ");
442 rStrm
.WriteCharPtr(" } ");
447 TAG_OFF_LF( OOO_STRING_SVTOOLS_HTML_style
);
451 TAG_OFF_LF( OOO_STRING_SVTOOLS_HTML_head
);
454 void ScHTMLExport::WriteOverview()
456 if ( nUsedTables
<= 1 )
461 IncIndent(1); TAG_ON( OOO_STRING_SVTOOLS_HTML_parabreak
); TAG_ON_LF( OOO_STRING_SVTOOLS_HTML_center
);
462 TAG_ON( OOO_STRING_SVTOOLS_HTML_head1
);
463 OUT_STR( ScResId( STR_OVERVIEW
) );
464 TAG_OFF_LF( OOO_STRING_SVTOOLS_HTML_head1
);
468 const SCTAB nCount
= pDoc
->GetTableCount();
469 for ( SCTAB nTab
= 0; nTab
< nCount
; nTab
++ )
471 if ( !IsEmptyTable( nTab
) )
473 pDoc
->GetName( nTab
, aStr
);
474 rStrm
.WriteCharPtr( "<A HREF=\"#table" )
475 .WriteOString( OString::number(nTab
) )
476 .WriteCharPtr( "\">" );
478 rStrm
.WriteCharPtr( "</A>" );
479 TAG_ON_LF( OOO_STRING_SVTOOLS_HTML_linebreak
);
483 IncIndent(-1); OUT_LF();
484 IncIndent(-1); TAG_OFF( OOO_STRING_SVTOOLS_HTML_center
); TAG_OFF_LF( OOO_STRING_SVTOOLS_HTML_parabreak
);
487 const SfxItemSet
& ScHTMLExport::PageDefaults( SCTAB nTab
)
489 SfxStyleSheetBasePool
* pStylePool
= pDoc
->GetStyleSheetPool();
490 SfxStyleSheetBase
* pStyleSheet
= nullptr;
491 OSL_ENSURE( pStylePool
, "StylePool not found! :-(" );
493 // remember defaults for compare in WriteCell
494 if ( !aHTMLStyle
.bInitialized
)
496 pStyleSheet
= pStylePool
->Find(
497 ScResId(STR_STYLENAME_STANDARD
),
498 SfxStyleFamily::Para
);
499 OSL_ENSURE( pStyleSheet
, "ParaStyle not found! :-(" );
501 pStyleSheet
= pStylePool
->First(SfxStyleFamily::Para
);
502 const SfxItemSet
& rSetPara
= pStyleSheet
->GetItemSet();
504 aHTMLStyle
.nDefaultScriptType
= ScGlobal::GetDefaultScriptType();
505 aHTMLStyle
.aFontFamilyName
= static_cast<const SvxFontItem
&>((rSetPara
.Get(
506 ScGlobal::GetScriptedWhichID(
507 aHTMLStyle
.nDefaultScriptType
, ATTR_FONT
508 )))).GetFamilyName();
509 aHTMLStyle
.nFontHeight
= static_cast<const SvxFontHeightItem
&>((rSetPara
.Get(
510 ScGlobal::GetScriptedWhichID(
511 aHTMLStyle
.nDefaultScriptType
, ATTR_FONT_HEIGHT
513 aHTMLStyle
.nFontSizeNumber
= GetFontSizeNumber( static_cast< sal_uInt16
>( aHTMLStyle
.nFontHeight
) );
516 // Page style sheet printer settings, e.g. for background graphics.
517 // There's only one background graphic in HTML!
518 pStyleSheet
= pStylePool
->Find( pDoc
->GetPageStyle( nTab
), SfxStyleFamily::Page
);
519 OSL_ENSURE( pStyleSheet
, "PageStyle not found! :-(" );
521 pStyleSheet
= pStylePool
->First(SfxStyleFamily::Page
);
522 const SfxItemSet
& rSet
= pStyleSheet
->GetItemSet();
523 if ( !aHTMLStyle
.bInitialized
)
525 const SvxBrushItem
* pBrushItem
= &rSet
.Get( ATTR_BACKGROUND
);
526 aHTMLStyle
.aBackgroundColor
= pBrushItem
->GetColor();
527 aHTMLStyle
.bInitialized
= true;
532 OString
ScHTMLExport::BorderToStyle(const char* pBorderName
,
533 const SvxBorderLine
* pLine
, bool& bInsertSemicolon
)
539 if ( bInsertSemicolon
)
543 aOut
.append(OString::Concat("border-") + pBorderName
+ ": ");
546 int nWidth
= pLine
->GetWidth();
547 int nPxWidth
= (nWidth
> 0) ?
548 std::max(o3tl::convert(nWidth
, o3tl::Length::twip
, o3tl::Length::px
), sal_Int64(1)) : 0;
549 aOut
.append(OString::number(nPxWidth
) + "px ");
550 switch (pLine
->GetBorderLineStyle())
552 case SvxBorderLineStyle::SOLID
:
553 aOut
.append("solid");
555 case SvxBorderLineStyle::DOTTED
:
556 aOut
.append("dotted");
558 case SvxBorderLineStyle::DASHED
:
559 case SvxBorderLineStyle::DASH_DOT
:
560 case SvxBorderLineStyle::DASH_DOT_DOT
:
561 aOut
.append("dashed");
563 case SvxBorderLineStyle::DOUBLE
:
564 case SvxBorderLineStyle::DOUBLE_THIN
:
565 case SvxBorderLineStyle::THINTHICK_SMALLGAP
:
566 case SvxBorderLineStyle::THINTHICK_MEDIUMGAP
:
567 case SvxBorderLineStyle::THINTHICK_LARGEGAP
:
568 case SvxBorderLineStyle::THICKTHIN_SMALLGAP
:
569 case SvxBorderLineStyle::THICKTHIN_MEDIUMGAP
:
570 case SvxBorderLineStyle::THICKTHIN_LARGEGAP
:
571 aOut
.append("double");
573 case SvxBorderLineStyle::EMBOSSED
:
574 aOut
.append("ridge");
576 case SvxBorderLineStyle::ENGRAVED
:
577 aOut
.append("groove");
579 case SvxBorderLineStyle::OUTSET
:
580 aOut
.append("outset");
582 case SvxBorderLineStyle::INSET
:
583 aOut
.append("inset");
586 aOut
.append("hidden");
592 snprintf( hex
, 7, "%06" SAL_PRIxUINT32
, static_cast<sal_uInt32
>( pLine
->GetColor().GetRGBColor() ) );
597 bInsertSemicolon
= true;
600 return aOut
.makeStringAndClear();
603 void ScHTMLExport::WriteBody()
605 const SfxItemSet
& rSet
= PageDefaults( bAll
? 0 : aRange
.aStart
.Tab() );
606 const SvxBrushItem
* pBrushItem
= &rSet
.Get( ATTR_BACKGROUND
);
608 // default text color black
609 if (!mbSkipHeaderFooter
)
611 rStrm
.WriteChar( '<' ).WriteCharPtr( OOO_STRING_SVTOOLS_HTML_body
);
615 if ( bAll
&& GPOS_NONE
!= pBrushItem
->GetGraphicPos() )
617 OUString aLink
= pBrushItem
->GetGraphicLink();
620 // Embedded graphic -> write using WriteGraphic
621 if( aLink
.isEmpty() )
623 const Graphic
* pGrf
= pBrushItem
->GetGraphic();
626 // Save graphic as (JPG) file
627 aGrfNm
= aStreamPath
;
628 ErrCode nErr
= XOutBitmap::WriteGraphic( *pGrf
, aGrfNm
,
629 "JPG", XOutFlags::UseNativeIfPossible
);
630 if( !nErr
) // Contains errors, as we have nothing to output
632 aGrfNm
= URIHelper::SmartRel2Abs(
633 INetURLObject(aBaseURL
),
634 aGrfNm
, URIHelper::GetMaybeFileHdl());
642 if( bCopyLocalFileToINet
)
644 CopyLocalFileToINet( aGrfNm
, aStreamPath
);
647 aGrfNm
= URIHelper::SmartRel2Abs(
648 INetURLObject(aBaseURL
),
649 aGrfNm
, URIHelper::GetMaybeFileHdl());
652 if( !aLink
.isEmpty() )
654 rStrm
.WriteChar( ' ' ).WriteCharPtr( OOO_STRING_SVTOOLS_HTML_O_background
).WriteCharPtr( "=\"" );
655 OUT_STR( URIHelper::simpleNormalizedMakeRelative(
657 aLink
) ).WriteChar( '\"' );
661 if ( !aHTMLStyle
.aBackgroundColor
.IsTransparent() )
662 { // A transparent background color should always result in default
663 // background of the browser. Also, HTMLOutFuncs::Out_Color() writes
664 // black #000000 for COL_AUTO which is the same as white #ffffff with
665 // transparency set to 0xff, our default background.
666 OUT_SP_CSTR_ASS( OOO_STRING_SVTOOLS_HTML_O_bgcolor
);
667 HTMLOutFuncs::Out_Color( rStrm
, aHTMLStyle
.aBackgroundColor
);
670 rStrm
.WriteChar( '>' ); OUT_LF();
678 if (!mbSkipHeaderFooter
)
679 TAG_OFF_LF( OOO_STRING_SVTOOLS_HTML_body
);
682 void ScHTMLExport::WriteTables()
684 const SCTAB nTabCount
= pDoc
->GetTableCount();
685 const OUString
aStrTable( ScResId( SCSTR_TABLE
) );
694 SCCOL nStartColFix
= 0;
695 SCROW nStartRowFix
= 0;
696 SCCOL nEndColFix
= 0;
697 SCROW nEndRowFix
= 0;
698 ScDrawLayer
* pDrawLayer
= pDoc
->GetDrawLayer();
702 nEndTab
= nTabCount
- 1;
706 nStartCol
= nStartColFix
= aRange
.aStart
.Col();
707 nStartRow
= nStartRowFix
= aRange
.aStart
.Row();
708 nStartTab
= aRange
.aStart
.Tab();
709 nEndCol
= nEndColFix
= aRange
.aEnd
.Col();
710 nEndRow
= nEndRowFix
= aRange
.aEnd
.Row();
711 nEndTab
= aRange
.aEnd
.Tab();
713 SCTAB nTableStrNum
= 1;
714 for ( SCTAB nTab
=nStartTab
; nTab
<=nEndTab
; nTab
++ )
716 if ( !pDoc
->IsVisible( nTab
) )
721 if ( !GetDataArea( nTab
, nStartCol
, nStartRow
, nEndCol
, nEndRow
) )
724 if ( nUsedTables
> 1 )
726 aStrOut
= aStrTable
+ " " + OUString::number( nTableStrNum
++ ) + ": ";
731 rStrm
.WriteCharPtr( "<A NAME=\"table" )
732 .WriteOString( OString::number(nTab
) )
733 .WriteCharPtr( "\">" );
734 TAG_ON( OOO_STRING_SVTOOLS_HTML_head1
);
736 TAG_ON( OOO_STRING_SVTOOLS_HTML_emphasis
);
738 pDoc
->GetName( nTab
, aStr
);
741 TAG_OFF( OOO_STRING_SVTOOLS_HTML_emphasis
);
742 TAG_OFF( OOO_STRING_SVTOOLS_HTML_head1
);
743 rStrm
.WriteCharPtr( "</A>" ); OUT_LF();
748 nStartCol
= nStartColFix
;
749 nStartRow
= nStartRowFix
;
750 nEndCol
= nEndColFix
;
751 nEndRow
= nEndRowFix
;
752 if ( !TrimDataArea( nTab
, nStartCol
, nStartRow
, nEndCol
, nEndRow
) )
757 OStringBuffer
aByteStrOut(OOO_STRING_SVTOOLS_HTML_table
);
759 bTabHasGraphics
= bTabAlignedLeft
= false;
760 if ( bAll
&& pDrawLayer
)
761 PrepareGraphics( pDrawLayer
, nTab
, nStartCol
, nStartRow
,
765 if ( bTabAlignedLeft
)
767 aByteStrOut
.append(" " OOO_STRING_SVTOOLS_HTML_O_align
769 OOO_STRING_SVTOOLS_HTML_AL_left
"\"");
771 // ALIGN=LEFT allow text and graphics to flow around
773 aByteStrOut
.append(" " OOO_STRING_SVTOOLS_HTML_O_cellspacing
775 OString::number(nCellSpacing
) + "\"");
777 // BORDER=0, we do the styling of the cells in <TD>
778 aByteStrOut
.append(" " OOO_STRING_SVTOOLS_HTML_O_border
"=\"0\"");
779 IncIndent(1); TAG_ON_LF( aByteStrOut
.makeStringAndClear().getStr() );
781 // --- <COLGROUP> ----
783 SCCOL nCol
= nStartCol
;
784 sal_Int32 nWidth
= 0;
786 while( nCol
<= nEndCol
)
788 if( pDoc
->ColHidden(nCol
, nTab
) )
794 if( nWidth
!= ToPixel( pDoc
->GetColWidth( nCol
, nTab
) ) )
798 TAG_ON(lcl_getColGroupString(nSpan
, nWidth
).getStr());
799 TAG_OFF_LF( OOO_STRING_SVTOOLS_HTML_colgroup
);
801 nWidth
= ToPixel( pDoc
->GetColWidth( nCol
, nTab
) );
810 TAG_ON(lcl_getColGroupString(nSpan
, nWidth
).getStr());
811 TAG_OFF_LF( OOO_STRING_SVTOOLS_HTML_colgroup
);
815 // <TBODY> // Re-enable only when THEAD and TFOOT are exported
816 // IncIndent(1); TAG_ON_LF( OOO_STRING_SVTOOLS_HTML_tbody );
817 // At least old (3.x, 4.x?) Netscape doesn't follow <TABLE COLS=n> and
818 // <COL WIDTH=x> specified, but needs a width at every column.
819 bool bHasHiddenRows
= pDoc
->HasHiddenRows(nStartRow
, nEndRow
, nTab
);
820 // We need to cache sc::ColumnBlockPosition per each column.
821 std::vector
< sc::ColumnBlockPosition
> blockPos( nEndCol
- nStartCol
+ 1 );
822 for( SCCOL i
= nStartCol
; i
<= nEndCol
; ++i
)
823 pDoc
->InitColumnBlockPosition( blockPos
[ i
- nStartCol
], nTab
, i
);
824 for ( SCROW nRow
=nStartRow
; nRow
<=nEndRow
; nRow
++ )
826 if ( bHasHiddenRows
&& pDoc
->RowHidden(nRow
, nTab
) )
828 nRow
= pDoc
->FirstVisibleRow(nRow
+1, nEndRow
, nTab
);
833 IncIndent(1); TAG_ON_LF( OOO_STRING_SVTOOLS_HTML_tablerow
);
834 bTableDataHeight
= true; // height at every first cell of each row
835 for ( SCCOL nCol2
=nStartCol
; nCol2
<=nEndCol
; nCol2
++ )
837 if ( pDoc
->ColHidden(nCol2
, nTab
) )
840 if ( nCol2
== nEndCol
)
842 WriteCell( blockPos
[ nCol2
- nStartCol
], nCol2
, nRow
, nTab
);
843 bTableDataHeight
= false;
846 if ( nRow
== nEndRow
)
848 TAG_OFF_LF( OOO_STRING_SVTOOLS_HTML_tablerow
);
850 // TODO: Uncomment later
851 // IncIndent(-1); TAG_OFF_LF( OOO_STRING_SVTOOLS_HTML_tbody );
853 IncIndent(-1); TAG_OFF_LF( OOO_STRING_SVTOOLS_HTML_table
);
855 if ( bTabHasGraphics
&& !mbSkipImages
)
857 // the rest that is not in a cell
858 size_t ListSize
= aGraphList
.size();
859 for ( size_t i
= 0; i
< ListSize
; ++i
)
861 ScHTMLGraphEntry
* pE
= &aGraphList
[ i
];
863 WriteGraphEntry( pE
);
866 if ( bTabAlignedLeft
)
868 // clear <TABLE ALIGN=LEFT> with <BR CLEAR=LEFT>
869 aByteStrOut
.append(OOO_STRING_SVTOOLS_HTML_linebreak
);
870 aByteStrOut
.append(' ').
871 append(OOO_STRING_SVTOOLS_HTML_O_clear
).append('=').
872 append(OOO_STRING_SVTOOLS_HTML_AL_left
);
873 TAG_ON_LF( aByteStrOut
.makeStringAndClear().getStr() );
878 OUT_COMMENT( "**************************************************************************" );
882 void ScHTMLExport::WriteCell( sc::ColumnBlockPosition
& rBlockPos
, SCCOL nCol
, SCROW nRow
, SCTAB nTab
)
884 ScAddress
aPos( nCol
, nRow
, nTab
);
885 ScRefCellValue
aCell(*pDoc
, aPos
, rBlockPos
);
886 const ScPatternAttr
* pAttr
= pDoc
->GetPattern( nCol
, nRow
, nTab
);
887 const SfxItemSet
* pCondItemSet
= pDoc
->GetCondResult( nCol
, nRow
, nTab
, &aCell
);
889 const ScMergeFlagAttr
& rMergeFlagAttr
= pAttr
->GetItem( ATTR_MERGE_FLAG
, pCondItemSet
);
890 if ( rMergeFlagAttr
.IsOverlapped() )
893 ScHTMLGraphEntry
* pGraphEntry
= nullptr;
894 if ( bTabHasGraphics
&& !mbSkipImages
)
896 size_t ListSize
= aGraphList
.size();
897 for ( size_t i
= 0; i
< ListSize
; ++i
)
899 ScHTMLGraphEntry
* pE
= &aGraphList
[ i
];
900 if ( pE
->bInCell
&& pE
->aRange
.Contains( aPos
) )
902 if ( pE
->aRange
.aStart
== aPos
)
908 return ; // Is a Col/RowSpan, Overlapped
913 sal_uInt32 nFormat
= pAttr
->GetNumberFormat( pFormatter
);
914 bool bValueData
= aCell
.hasNumeric();
915 SvtScriptType nScriptType
= SvtScriptType::NONE
;
916 if (!aCell
.isEmpty())
917 nScriptType
= pDoc
->GetScriptType(nCol
, nRow
, nTab
, &aCell
);
919 if ( nScriptType
== SvtScriptType::NONE
)
920 nScriptType
= aHTMLStyle
.nDefaultScriptType
;
922 OStringBuffer
aStrTD(OOO_STRING_SVTOOLS_HTML_tabledata
);
924 // border of the cells
925 const SvxBoxItem
* pBorder
= pDoc
->GetAttr( nCol
, nRow
, nTab
, ATTR_BORDER
);
926 if ( pBorder
&& (pBorder
->GetTop() || pBorder
->GetBottom() || pBorder
->GetLeft() || pBorder
->GetRight()) )
928 aStrTD
.append(" " OOO_STRING_SVTOOLS_HTML_style
"=\"");
930 bool bInsertSemicolon
= false;
931 aStrTD
.append(BorderToStyle("top", pBorder
->GetTop(),
933 aStrTD
.append(BorderToStyle("bottom", pBorder
->GetBottom(),
935 aStrTD
.append(BorderToStyle("left", pBorder
->GetLeft(),
937 aStrTD
.append(BorderToStyle("right", pBorder
->GetRight(),
944 sal_uInt16 nHeightPixel
;
946 const ScMergeAttr
& rMergeAttr
= pAttr
->GetItem( ATTR_MERGE
, pCondItemSet
);
947 if ( pGraphEntry
|| rMergeAttr
.IsMerged() )
953 nC
= std::max( SCCOL(pGraphEntry
->aRange
.aEnd
.Col() - nCol
+ 1),
954 rMergeAttr
.GetColMerge() );
956 nC
= rMergeAttr
.GetColMerge();
959 aStrTD
.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_colspan
).
960 append('=').append(static_cast<sal_Int32
>(nC
));
962 for ( jC
=nCol
, v
=0; jC
<nC
; jC
++ )
963 v
+= pDoc
->GetColWidth( jC
, nTab
);
967 nR
= std::max( SCROW(pGraphEntry
->aRange
.aEnd
.Row() - nRow
+ 1),
968 rMergeAttr
.GetRowMerge() );
970 nR
= rMergeAttr
.GetRowMerge();
973 aStrTD
.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_rowspan
).
974 append('=').append(static_cast<sal_Int32
>(nR
));
976 v
= pDoc
->GetRowHeight( nRow
, nR
-1, nTab
);
977 nHeightPixel
= ToPixel( static_cast< sal_uInt16
>( v
) );
980 nHeightPixel
= ToPixel( pDoc
->GetRowHeight( nRow
, nTab
) );
983 nHeightPixel
= ToPixel( pDoc
->GetRowHeight( nRow
, nTab
) );
985 if ( bTableDataHeight
)
987 aStrTD
.append(" " OOO_STRING_SVTOOLS_HTML_O_height
"=\"" +
988 OString::number(nHeightPixel
) + "\"");
991 const SvxFontItem
& rFontItem
= static_cast<const SvxFontItem
&>( pAttr
->GetItem(
992 ScGlobal::GetScriptedWhichID( nScriptType
, ATTR_FONT
),
995 const SvxFontHeightItem
& rFontHeightItem
= static_cast<const SvxFontHeightItem
&>(
996 pAttr
->GetItem( ScGlobal::GetScriptedWhichID( nScriptType
,
997 ATTR_FONT_HEIGHT
), pCondItemSet
) );
999 const SvxWeightItem
& rWeightItem
= static_cast<const SvxWeightItem
&>( pAttr
->GetItem(
1000 ScGlobal::GetScriptedWhichID( nScriptType
, ATTR_FONT_WEIGHT
),
1003 const SvxPostureItem
& rPostureItem
= static_cast<const SvxPostureItem
&>(
1004 pAttr
->GetItem( ScGlobal::GetScriptedWhichID( nScriptType
,
1005 ATTR_FONT_POSTURE
), pCondItemSet
) );
1007 const SvxUnderlineItem
& rUnderlineItem
=
1008 pAttr
->GetItem( ATTR_FONT_UNDERLINE
, pCondItemSet
);
1010 const SvxCrossedOutItem
& rCrossedOutItem
=
1011 pAttr
->GetItem( ATTR_FONT_CROSSEDOUT
, pCondItemSet
);
1013 const SvxColorItem
& rColorItem
= pAttr
->GetItem(
1014 ATTR_FONT_COLOR
, pCondItemSet
);
1016 const SvxHorJustifyItem
& rHorJustifyItem
=
1017 pAttr
->GetItem( ATTR_HOR_JUSTIFY
, pCondItemSet
);
1019 const SvxVerJustifyItem
& rVerJustifyItem
=
1020 pAttr
->GetItem( ATTR_VER_JUSTIFY
, pCondItemSet
);
1022 const SvxBrushItem
& rBrushItem
= pAttr
->GetItem(
1023 ATTR_BACKGROUND
, pCondItemSet
);
1026 if ( rBrushItem
.GetColor().GetAlpha() == 0 )
1027 aBgColor
= aHTMLStyle
.aBackgroundColor
; // No unwanted background color
1029 aBgColor
= rBrushItem
.GetColor();
1031 bool bBold
= ( WEIGHT_BOLD
<= rWeightItem
.GetWeight() );
1032 bool bItalic
= ( ITALIC_NONE
!= rPostureItem
.GetPosture() );
1033 bool bUnderline
= ( LINESTYLE_NONE
!= rUnderlineItem
.GetLineStyle() );
1034 bool bCrossedOut
= ( STRIKEOUT_SINGLE
<= rCrossedOutItem
.GetStrikeout() );
1035 bool bSetFontColor
= ( COL_AUTO
!= rColorItem
.GetValue() ); // default is AUTO now
1036 bool bSetFontName
= ( aHTMLStyle
.aFontFamilyName
!= rFontItem
.GetFamilyName() );
1037 sal_uInt16 nSetFontSizeNumber
= 0;
1038 sal_uInt32 nFontHeight
= rFontHeightItem
.GetHeight();
1039 if ( nFontHeight
!= aHTMLStyle
.nFontHeight
)
1041 nSetFontSizeNumber
= GetFontSizeNumber( static_cast<sal_uInt16
>(nFontHeight
) );
1042 if ( nSetFontSizeNumber
== aHTMLStyle
.nFontSizeNumber
)
1043 nSetFontSizeNumber
= 0; // no difference, don't set
1046 bool bSetFont
= (bSetFontColor
|| bSetFontName
|| nSetFontSizeNumber
);
1048 //! TODO: we could entirely use CSS1 here instead, but that would exclude
1049 //! Netscape 3.0 and Netscape 4.x without JavaScript enabled.
1050 //! Do we want that?
1052 switch( rHorJustifyItem
.GetValue() )
1054 case SvxCellHorJustify::Standard
:
1055 pChar
= (bValueData
? OOO_STRING_SVTOOLS_HTML_AL_right
: OOO_STRING_SVTOOLS_HTML_AL_left
);
1057 case SvxCellHorJustify::Center
: pChar
= OOO_STRING_SVTOOLS_HTML_AL_center
; break;
1058 case SvxCellHorJustify::Block
: pChar
= OOO_STRING_SVTOOLS_HTML_AL_justify
; break;
1059 case SvxCellHorJustify::Right
: pChar
= OOO_STRING_SVTOOLS_HTML_AL_right
; break;
1060 case SvxCellHorJustify::Left
:
1061 case SvxCellHorJustify::Repeat
:
1062 default: pChar
= OOO_STRING_SVTOOLS_HTML_AL_left
; break;
1065 aStrTD
.append(" " OOO_STRING_SVTOOLS_HTML_O_align
"=\"" +
1066 OString::Concat(pChar
) + "\"");
1068 switch( rVerJustifyItem
.GetValue() )
1070 case SvxCellVerJustify::Top
: pChar
= OOO_STRING_SVTOOLS_HTML_VA_top
; break;
1071 case SvxCellVerJustify::Center
: pChar
= OOO_STRING_SVTOOLS_HTML_VA_middle
; break;
1072 case SvxCellVerJustify::Bottom
: pChar
= OOO_STRING_SVTOOLS_HTML_VA_bottom
; break;
1073 case SvxCellVerJustify::Standard
:
1074 default: pChar
= nullptr;
1078 aStrTD
.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_valign
).
1079 append('=').append(pChar
);
1082 if ( aHTMLStyle
.aBackgroundColor
!= aBgColor
)
1084 aStrTD
.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_bgcolor
).
1086 aStrTD
.append(lcl_makeHTMLColorTriplet(aBgColor
));
1092 switch (aCell
.getType())
1094 case CELLTYPE_VALUE
:
1095 fVal
= aCell
.getDouble();
1096 if ( bCalcAsShown
&& fVal
!= 0.0 )
1097 fVal
= pDoc
->RoundValueAsShown( fVal
, nFormat
);
1099 case CELLTYPE_FORMULA
:
1100 fVal
= aCell
.getFormula()->GetValue();
1103 OSL_FAIL( "value data with unsupported cell type" );
1107 aStrTD
.append(HTMLOutFuncs::CreateTableDataOptionsValNum(bValueData
, fVal
,
1108 nFormat
, *pFormatter
, &aNonConvertibleChars
));
1110 TAG_ON(aStrTD
.makeStringAndClear().getStr());
1112 //write the note for this as the first thing in the tag
1113 ScPostIt
* pNote
= pDoc
->HasNote(aPos
) ? pDoc
->GetNote(aPos
) : nullptr;
1116 //create the comment indicator
1117 OString aStr
= OOO_STRING_SVTOOLS_HTML_anchor
" "
1118 OOO_STRING_SVTOOLS_HTML_O_class
"=\"comment-indicator\"";
1119 TAG_ON(aStr
.getStr());
1120 TAG_OFF(OOO_STRING_SVTOOLS_HTML_anchor
);
1123 //create the element holding the contents
1124 //this is a bit naive, since it doesn't separate
1125 //lines into html breaklines yet
1126 TAG_ON(OOO_STRING_SVTOOLS_HTML_comment2
);
1127 OUT_STR( pNote
->GetText() );
1128 TAG_OFF(OOO_STRING_SVTOOLS_HTML_comment2
);
1132 if ( bBold
) TAG_ON( OOO_STRING_SVTOOLS_HTML_bold
);
1133 if ( bItalic
) TAG_ON( OOO_STRING_SVTOOLS_HTML_italic
);
1134 if ( bUnderline
) TAG_ON( OOO_STRING_SVTOOLS_HTML_underline
);
1135 if ( bCrossedOut
) TAG_ON( OOO_STRING_SVTOOLS_HTML_strikethrough
);
1139 OStringBuffer
aStr(OOO_STRING_SVTOOLS_HTML_font
);
1142 aStr
.append(" " OOO_STRING_SVTOOLS_HTML_O_face
"=\"");
1144 if (!rFontItem
.GetFamilyName().isEmpty())
1146 const OUString
& rList
= rFontItem
.GetFamilyName();
1147 for (sal_Int32 nPos
{0};;)
1149 OString aTmpStr
= HTMLOutFuncs::ConvertStringToHTML(
1150 rList
.getToken( 0, ';', nPos
),
1151 &aNonConvertibleChars
);
1152 aStr
.append(aTmpStr
);
1161 if ( nSetFontSizeNumber
)
1163 aStr
.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_size
).
1164 append('=').append(static_cast<sal_Int32
>(nSetFontSizeNumber
));
1166 if ( bSetFontColor
)
1168 Color aColor
= rColorItem
.GetValue();
1170 // always export automatic text color as black
1171 if ( aColor
== COL_AUTO
)
1174 aStr
.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_color
).
1175 append('=').append(lcl_makeHTMLColorTriplet(aColor
));
1177 TAG_ON(aStr
.makeStringAndClear().getStr());
1181 bool bWriteHyperLink(false);
1182 if (aCell
.getType() == CELLTYPE_FORMULA
)
1184 ScFormulaCell
* pFCell
= aCell
.getFormula();
1185 if (pFCell
->IsHyperLinkCell())
1188 pFCell
->GetURLResult(aURL
, aCellText
);
1189 bWriteHyperLink
= true;
1193 if (bWriteHyperLink
)
1195 OString aURLStr
= HTMLOutFuncs::ConvertStringToHTML(aURL
, &aNonConvertibleChars
);
1196 OString aStr
= OOO_STRING_SVTOOLS_HTML_anchor
" " OOO_STRING_SVTOOLS_HTML_O_href
"=\"" + aURLStr
+ "\"";
1197 TAG_ON(aStr
.getStr());
1201 bool bFieldText
= false;
1203 const Color
* pColor
;
1204 switch (aCell
.getType())
1206 case CELLTYPE_EDIT
:
1207 bFieldText
= WriteFieldText(aCell
.getEditText());
1212 aStrOut
= ScCellFormat::GetString(aCell
, nFormat
, &pColor
, *pFormatter
, *pDoc
);
1217 if ( aStrOut
.isEmpty() )
1219 TAG_ON( OOO_STRING_SVTOOLS_HTML_linebreak
); // No completely empty line
1223 sal_Int32 nPos
= aStrOut
.indexOf( '\n' );
1230 sal_Int32 nStartPos
= 0;
1233 OUString aSingleLine
= aStrOut
.copy( nStartPos
, nPos
- nStartPos
);
1234 OUT_STR( aSingleLine
);
1235 TAG_ON( OOO_STRING_SVTOOLS_HTML_linebreak
);
1236 nStartPos
= nPos
+ 1;
1238 while( ( nPos
= aStrOut
.indexOf( '\n', nStartPos
) ) != -1 );
1239 OUString aSingleLine
= aStrOut
.copy( nStartPos
);
1240 OUT_STR( aSingleLine
);
1245 WriteGraphEntry( pGraphEntry
);
1247 if (bWriteHyperLink
) { TAG_OFF(OOO_STRING_SVTOOLS_HTML_anchor
); }
1249 if ( bSetFont
) TAG_OFF( OOO_STRING_SVTOOLS_HTML_font
);
1250 if ( bCrossedOut
) TAG_OFF( OOO_STRING_SVTOOLS_HTML_strikethrough
);
1251 if ( bUnderline
) TAG_OFF( OOO_STRING_SVTOOLS_HTML_underline
);
1252 if ( bItalic
) TAG_OFF( OOO_STRING_SVTOOLS_HTML_italic
);
1253 if ( bBold
) TAG_OFF( OOO_STRING_SVTOOLS_HTML_bold
);
1255 TAG_OFF_LF( OOO_STRING_SVTOOLS_HTML_tabledata
);
1258 bool ScHTMLExport::WriteFieldText( const EditTextObject
* pData
)
1260 bool bFields
= false;
1261 // text and anchor of URL fields, Doc-Engine is a ScFieldEditEngine
1262 EditEngine
& rEngine
= pDoc
->GetEditEngine();
1263 rEngine
.SetText( *pData
);
1264 sal_Int32 nParas
= rEngine
.GetParagraphCount();
1267 ESelection
aSel( 0, 0, nParas
-1, rEngine
.GetTextLen( nParas
-1 ) );
1268 SfxItemSet
aSet( rEngine
.GetAttribs( aSel
) );
1269 SfxItemState eFieldState
= aSet
.GetItemState( EE_FEATURE_FIELD
, false );
1270 if ( eFieldState
== SfxItemState::DONTCARE
|| eFieldState
== SfxItemState::SET
)
1275 bool bOldUpdateMode
= rEngine
.SetUpdateLayout( true ); // no portions if not formatted
1276 for ( sal_Int32 nPar
=0; nPar
< nParas
; nPar
++ )
1279 TAG_ON( OOO_STRING_SVTOOLS_HTML_linebreak
);
1280 std::vector
<sal_Int32
> aPortions
;
1281 rEngine
.GetPortions( nPar
, aPortions
);
1282 sal_Int32 nStart
= 0;
1283 for ( const sal_Int32 nEnd
: aPortions
)
1285 ESelection
aSel( nPar
, nStart
, nPar
, nEnd
);
1287 // fields are single characters
1288 if ( nEnd
== nStart
+1 )
1290 SfxItemSet aSet
= rEngine
.GetAttribs( aSel
);
1291 if ( const SvxFieldItem
* pFieldItem
= aSet
.GetItemIfSet( EE_FEATURE_FIELD
, false ) )
1293 const SvxFieldData
* pField
= pFieldItem
->GetField();
1294 if (const SvxURLField
* pURLField
= dynamic_cast<const SvxURLField
*>(pField
))
1297 rStrm
.WriteChar( '<' ).WriteCharPtr( OOO_STRING_SVTOOLS_HTML_anchor
).WriteChar( ' ' ).WriteCharPtr( OOO_STRING_SVTOOLS_HTML_O_href
).WriteCharPtr( "=\"" );
1298 OUT_STR( pURLField
->GetURL() );
1299 rStrm
.WriteCharPtr( "\">" );
1300 OUT_STR( pURLField
->GetRepresentation() );
1301 rStrm
.WriteCharPtr( "</" ).WriteCharPtr( OOO_STRING_SVTOOLS_HTML_anchor
).WriteChar( '>' );
1306 OUT_STR( rEngine
.GetText( aSel
) );
1310 rEngine
.SetUpdateLayout( bOldUpdateMode
);
1315 void ScHTMLExport::CopyLocalFileToINet( OUString
& rFileNm
,
1316 std::u16string_view rTargetNm
)
1318 INetURLObject aFileUrl
, aTargetUrl
;
1319 aFileUrl
.SetSmartURL( rFileNm
);
1320 aTargetUrl
.SetSmartURL( rTargetNm
);
1321 if( !(INetProtocol::File
== aFileUrl
.GetProtocol() &&
1322 ( INetProtocol::File
!= aTargetUrl
.GetProtocol() &&
1323 INetProtocol::Ftp
<= aTargetUrl
.GetProtocol() &&
1324 INetProtocol::Javascript
>= aTargetUrl
.GetProtocol())) )
1329 // Did we already move the file?
1330 std::map
<OUString
, OUString
>::iterator it
= pFileNameMap
->find( rFileNm
);
1331 if( it
!= pFileNameMap
->end() )
1333 rFileNm
= it
->second
;
1339 pFileNameMap
.reset( new std::map
<OUString
, OUString
> );
1343 SvFileStream
aTmp( aFileUrl
.PathToFileName(), StreamMode::READ
);
1345 OUString aSrc
= rFileNm
;
1346 OUString aDest
= aTargetUrl
.GetPartBeforeLastName() + aFileUrl
.GetLastName();
1348 SfxMedium
aMedium( aDest
, StreamMode::WRITE
| StreamMode::SHARE_DENYNONE
);
1351 SvFileStream
aCpy( aMedium
.GetPhysicalName(), StreamMode::WRITE
);
1352 aCpy
.WriteStream( aTmp
);
1359 bRet
= ERRCODE_NONE
== aMedium
.GetError();
1363 pFileNameMap
->insert( std::make_pair( aSrc
, aDest
) );
1368 void ScHTMLExport::IncIndent( short nVal
)
1370 sIndent
[nIndent
] = '\t';
1371 nIndent
= nIndent
+ nVal
;
1374 else if ( nIndent
> nIndentMax
)
1375 nIndent
= nIndentMax
;
1376 sIndent
[nIndent
] = 0;
1379 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */