dr78: #i96587# oox - import BIFF8 cell notes
This commit is contained in:
parent
1ed3654a1c
commit
b03baea914
8 changed files with 135 additions and 39 deletions
|
@ -425,6 +425,7 @@ const sal_uInt16 BIFF_ID_MTHREADSETTINGS = 0x089A;
|
|||
const sal_uInt16 BIFF_ID_MULTBLANK = 0x00BE;
|
||||
const sal_uInt16 BIFF_ID_MULTRK = 0x00BD;
|
||||
const sal_uInt16 BIFF_ID_NOTE = 0x001C;
|
||||
const sal_uInt16 BIFF_ID_NOTESOUND = 0x0096;
|
||||
const sal_uInt16 BIFF2_ID_NUMBER = 0x0003;
|
||||
const sal_uInt16 BIFF3_ID_NUMBER = 0x0203;
|
||||
const sal_uInt16 BIFF_ID_OBJ = 0x005D;
|
||||
|
|
|
@ -40,8 +40,11 @@ struct CommentModel
|
|||
{
|
||||
::com::sun::star::table::CellRangeAddress
|
||||
maRange; /// Position of the comment in the worksheet.
|
||||
RichStringRef mxText; /// Formatted text of the comment.
|
||||
sal_Int32 mnAuthorId; /// Identifier of the comment's author.
|
||||
RichStringRef mxText; /// Formatted text of the comment (not used in BIFF8).
|
||||
::rtl::OUString maAuthor; /// Comment author (BIFF8 only).
|
||||
sal_Int32 mnAuthorId; /// Identifier of the comment's author (OOXML and BIFF12 only).
|
||||
sal_uInt16 mnObjId; /// Drawing object identifier (BIFF8 only).
|
||||
bool mbVisible; /// True = comment is always shown (BIFF2-BIFF8 only).
|
||||
|
||||
explicit CommentModel();
|
||||
};
|
||||
|
@ -66,6 +69,14 @@ public:
|
|||
/** Finalizes the formatted string of the comment. */
|
||||
void finalizeImport();
|
||||
|
||||
private:
|
||||
/** Reads a BIFF2-BIFF5 NOTE record. */
|
||||
void importNoteBiff2( BiffInputStream& rStrm );
|
||||
/** Reads a BIFF8 NOTE record. */
|
||||
void importNoteBiff8( BiffInputStream& rStrm );
|
||||
/** Reads a NOTESOUND record. */
|
||||
void importNoteSound( BiffInputStream& rStrm );
|
||||
|
||||
private:
|
||||
CommentModel maModel;
|
||||
};
|
||||
|
|
|
@ -39,6 +39,10 @@ namespace com { namespace sun { namespace star {
|
|||
namespace oox {
|
||||
namespace xls {
|
||||
|
||||
// ============================================================================
|
||||
|
||||
const sal_uInt16 BIFF_OBJ_INVALID_ID = 0;
|
||||
|
||||
// ============================================================================
|
||||
// Model structures for BIFF OBJ record data
|
||||
// ============================================================================
|
||||
|
|
|
@ -2520,6 +2520,8 @@ void WorkbookStreamObject::implDumpRecordBody()
|
|||
{
|
||||
dumpHex< sal_uInt16 >( "flags", "NOTE-FLAGS" );
|
||||
dumpDec< sal_uInt16 >( "obj-id" );
|
||||
dumpUniString( "author" );
|
||||
dumpUnused( 1 );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -2529,6 +2531,21 @@ void WorkbookStreamObject::implDumpRecordBody()
|
|||
}
|
||||
break;
|
||||
|
||||
case BIFF_ID_NOTESOUND:
|
||||
dumpHex< sal_uInt32 >( "identifier" );
|
||||
dumpDec< sal_uInt32 >( "total-data-size" );
|
||||
dumpDec< sal_uInt32 >( "wave-data-size" );
|
||||
if( dumpDec< sal_uInt32 >( "fmt-size" ) >= 16 )
|
||||
{
|
||||
dumpDec< sal_uInt16 >( "format", "NOTESOUND-FORMAT" );
|
||||
dumpDec< sal_uInt16 >( "channels" );
|
||||
dumpDec< sal_uInt32 >( "sampling-rate" );
|
||||
dumpDec< sal_uInt32 >( "data-rate" );
|
||||
dumpDec< sal_uInt16 >( "data-block-size" );
|
||||
dumpDec< sal_uInt16 >( "bits-per-sample" );
|
||||
}
|
||||
break;
|
||||
|
||||
case BIFF2_ID_NUMBER:
|
||||
case BIFF3_ID_NUMBER:
|
||||
dumpCellHeader( nRecId == BIFF2_ID_NUMBER );
|
||||
|
|
|
@ -324,7 +324,7 @@ multilist=RECORD-NAMES-BIFF4
|
|||
exclude=0x0206,0x0209,0x001E,0x0243
|
||||
0x0085=SHEET
|
||||
0x0088=,,,,,,SHEETSOFFSET,SHEETHEADER
|
||||
0x0090=,,,,,SOUND,SYNC
|
||||
0x0090=,,,,,,NOTESOUND,SYNC
|
||||
0x0098=LPR,STANDARDWIDTH,FNGROUPNAME,,FNGROUPCOUNT,,,
|
||||
0x00A0=SCL,PAGESETUP,FNPROTO,PROJEXTSHEET,,,,
|
||||
0x00A8=DRAGDROP,COORDLIST,,GCW,,,,
|
||||
|
@ -1441,6 +1441,18 @@ shortlist=IMGDATA-ENV,1,windows,apple
|
|||
|
||||
flagslist=NOTE-FLAGS-BIFF8
|
||||
0x0002=visible
|
||||
0x0080=row-hidden
|
||||
0x0100=col-hidden
|
||||
end
|
||||
|
||||
# NOTESOUND ------------------------------------------------------------------
|
||||
|
||||
constlist=NOTESOUND-FORMAT
|
||||
1=pcm
|
||||
3=ieee-float
|
||||
6=a-law
|
||||
7=mu-law
|
||||
0xFFFE=extensible
|
||||
end
|
||||
|
||||
# OBJ ------------------------------------------------------------------------
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
#include "oox/xls/addressconverter.hxx"
|
||||
#include "oox/xls/biffinputstream.hxx"
|
||||
#include "oox/xls/drawingfragment.hxx"
|
||||
#include "oox/xls/drawingmanager.hxx"
|
||||
|
||||
using ::rtl::OUString;
|
||||
using ::com::sun::star::uno::Reference;
|
||||
|
@ -56,8 +57,18 @@ namespace xls {
|
|||
|
||||
// ============================================================================
|
||||
|
||||
namespace {
|
||||
|
||||
const sal_uInt16 BIFF_NOTE_VISIBLE = 0x0002;
|
||||
|
||||
} // namespace
|
||||
|
||||
// ============================================================================
|
||||
|
||||
CommentModel::CommentModel() :
|
||||
mnAuthorId( -1 )
|
||||
mnAuthorId( -1 ),
|
||||
mnObjId( BIFF_OBJ_INVALID_ID ),
|
||||
mbVisible( false )
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -86,33 +97,29 @@ void Comment::importComment( RecordInputStream& rStrm )
|
|||
void Comment::importNote( BiffInputStream& rStrm )
|
||||
{
|
||||
BinAddress aBinAddr;
|
||||
sal_uInt16 nTotalLen;
|
||||
rStrm >> aBinAddr >> nTotalLen;
|
||||
rStrm >> aBinAddr;
|
||||
// cell range will be checked while inserting the comment into the document
|
||||
getAddressConverter().convertToCellRangeUnchecked( maModel.maRange, BinRange( aBinAddr ), getSheetIndex() );
|
||||
RichStringRef xNoteText = createText();
|
||||
|
||||
sal_uInt16 nPartLen = ::std::min( nTotalLen, static_cast< sal_uInt16 >( rStrm.getRemaining() ) );
|
||||
xNoteText->importCharArray( rStrm, nPartLen, getTextEncoding() );
|
||||
|
||||
nTotalLen = nTotalLen - nPartLen; // operator-=() gives compiler warning
|
||||
while( (nTotalLen > 0) && (rStrm.getNextRecId() == BIFF_ID_NOTE) && rStrm.startNextRecord() )
|
||||
// remaining record data is BIFF dependent
|
||||
switch( getBiff() )
|
||||
{
|
||||
rStrm >> aBinAddr >> nPartLen;
|
||||
OSL_ENSURE( aBinAddr.mnRow == 0xFFFF, "Comment::importNote - missing continuation NOTE record" );
|
||||
if( aBinAddr.mnRow == 0xFFFF )
|
||||
{
|
||||
OSL_ENSURE( nPartLen <= nTotalLen, "Comment::importNote - string too long" );
|
||||
// call to RichString::importCharArray() appends new text portion
|
||||
xNoteText->importCharArray( rStrm, nPartLen, getTextEncoding() );
|
||||
nTotalLen = nTotalLen - ::std::min( nTotalLen, nPartLen );
|
||||
}
|
||||
else
|
||||
{
|
||||
// seems to be a new note, rewind record, so worksheet fragment loop will find it
|
||||
rStrm.rewindRecord();
|
||||
nTotalLen = 0;
|
||||
}
|
||||
case BIFF2:
|
||||
case BIFF3:
|
||||
importNoteBiff2( rStrm );
|
||||
break;
|
||||
case BIFF4:
|
||||
case BIFF5:
|
||||
importNoteBiff2( rStrm );
|
||||
// in BIFF4 and BIFF5, comments can have an associated sound
|
||||
if( (rStrm.getNextRecId() == BIFF_ID_NOTESOUND) && rStrm.startNextRecord() )
|
||||
importNoteSound( rStrm );
|
||||
break;
|
||||
case BIFF8:
|
||||
importNoteBiff8( rStrm );
|
||||
break;
|
||||
case BIFF_UNKNOWN:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -135,12 +142,15 @@ void Comment::finalizeImport()
|
|||
Reference< XSheetAnnotations > xAnnos( xAnnosSupp->getAnnotations(), UNO_SET_THROW );
|
||||
// non-empty string required by note implementation (real text will be added below)
|
||||
xAnnos->insertNew( aNotePos, OUString( sal_Unicode( ' ' ) ) );
|
||||
// receive craeted note from cell (insertNew does not return the note)
|
||||
|
||||
// receive created note from cell (insertNew does not return the note)
|
||||
Reference< XSheetAnnotationAnchor > xAnnoAnchor( getCell( aNotePos ), UNO_QUERY_THROW );
|
||||
Reference< XSheetAnnotation > xAnno( xAnnoAnchor->getAnnotation(), UNO_SET_THROW );
|
||||
Reference< XSheetAnnotationShapeSupplier > xAnnoShapeSupp( xAnno, UNO_QUERY_THROW );
|
||||
Reference< XShape > xAnnoShape( xAnnoShapeSupp->getAnnotationShape(), UNO_SET_THROW );
|
||||
// convert shape formatting
|
||||
|
||||
// convert shape formatting and visibility
|
||||
sal_Bool bVisible = sal_True;
|
||||
switch( getFilterType() )
|
||||
{
|
||||
case FILTER_OOX:
|
||||
|
@ -150,17 +160,17 @@ void Comment::finalizeImport()
|
|||
pNoteShape->convertFormatting( xAnnoShape );
|
||||
// visibility
|
||||
const ::oox::vml::ShapeModel::ShapeClientDataPtr& rxClientData = pNoteShape->getShapeModel().mxClientData;
|
||||
bool bVisible = rxClientData.get() && rxClientData->mbVisible;
|
||||
xAnno->setIsVisible( bVisible );
|
||||
bVisible = rxClientData.get() && rxClientData->mbVisible;
|
||||
}
|
||||
break;
|
||||
case FILTER_BIFF:
|
||||
// notes are always hidden and unformatted in BIFF3-BIFF5
|
||||
xAnno->setIsVisible( sal_False );
|
||||
bVisible = maModel.mbVisible;
|
||||
break;
|
||||
case FILTER_UNKNOWN:
|
||||
break;
|
||||
}
|
||||
xAnno->setIsVisible( bVisible );
|
||||
|
||||
// insert text and convert text formatting
|
||||
maModel.mxText->finalizeImport();
|
||||
Reference< XText > xAnnoText( xAnnoShape, UNO_QUERY_THROW );
|
||||
|
@ -171,6 +181,52 @@ void Comment::finalizeImport()
|
|||
}
|
||||
}
|
||||
|
||||
// private --------------------------------------------------------------------
|
||||
|
||||
void Comment::importNoteBiff2( BiffInputStream& rStrm )
|
||||
{
|
||||
sal_uInt16 nTotalLen;
|
||||
rStrm >> nTotalLen;
|
||||
sal_uInt16 nPartLen = ::std::min( nTotalLen, static_cast< sal_uInt16 >( rStrm.getRemaining() ) );
|
||||
RichStringRef xNoteText = createText();
|
||||
xNoteText->importCharArray( rStrm, nPartLen, getTextEncoding() );
|
||||
|
||||
nTotalLen = nTotalLen - nPartLen; // operator-=() gives compiler warning
|
||||
while( (nTotalLen > 0) && (rStrm.getNextRecId() == BIFF_ID_NOTE) && rStrm.startNextRecord() )
|
||||
{
|
||||
sal_uInt16 nMarker;
|
||||
rStrm >> nMarker;
|
||||
rStrm.skip( 2 );
|
||||
rStrm >> nPartLen;
|
||||
OSL_ENSURE( nMarker == 0xFFFF, "Comment::importNoteBiff2 - missing continuation NOTE record" );
|
||||
if( nMarker == 0xFFFF )
|
||||
{
|
||||
OSL_ENSURE( nPartLen <= nTotalLen, "Comment::importNoteBiff2 - string too long" );
|
||||
// call to RichString::importCharArray() appends new text portion
|
||||
xNoteText->importCharArray( rStrm, nPartLen, getTextEncoding() );
|
||||
nTotalLen = nTotalLen - ::std::min( nTotalLen, nPartLen );
|
||||
}
|
||||
else
|
||||
{
|
||||
// seems to be a new note, rewind record, so worksheet fragment loop will find it
|
||||
rStrm.rewindRecord();
|
||||
nTotalLen = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Comment::importNoteBiff8( BiffInputStream& rStrm )
|
||||
{
|
||||
sal_uInt16 nFlags;
|
||||
rStrm >> nFlags >> maModel.mnObjId;
|
||||
maModel.maAuthor = rStrm.readUniString();
|
||||
maModel.mbVisible = getFlag( nFlags, BIFF_NOTE_VISIBLE );
|
||||
}
|
||||
|
||||
void Comment::importNoteSound( BiffInputStream& /*rStrm*/ )
|
||||
{
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
|
||||
CommentsBuffer::CommentsBuffer( const WorksheetHelper& rHelper ) :
|
||||
|
|
|
@ -51,8 +51,6 @@ namespace {
|
|||
|
||||
// OBJ record -----------------------------------------------------------------
|
||||
|
||||
const sal_uInt16 BIFF_OBJ_INVALID_ID = 0;
|
||||
|
||||
const sal_uInt16 BIFF_OBJTYPE_GROUP = 0;
|
||||
const sal_uInt16 BIFF_OBJTYPE_LINE = 1;
|
||||
const sal_uInt16 BIFF_OBJTYPE_RECTANGLE = 2;
|
||||
|
|
|
@ -804,6 +804,7 @@ bool BiffWorksheetFragment::importFragment()
|
|||
case BIFF_ID_HORPAGEBREAKS: importPageBreaks( true ); break;
|
||||
case BIFF_ID_ITERATION: rWorkbookSett.importIteration( mrStrm ); break;
|
||||
case BIFF_ID_LEFTMARGIN: rPageSett.importLeftMargin( mrStrm ); break;
|
||||
case BIFF_ID_NOTE: importNote(); break;
|
||||
case BIFF_ID_PANE: rSheetViewSett.importPane( mrStrm ); break;
|
||||
case BIFF_ID_PASSWORD: rWorksheetSett.importPassword( mrStrm ); break;
|
||||
case BIFF_ID_PRINTGRIDLINES: rPageSett.importPrintGridLines( mrStrm ); break;
|
||||
|
@ -823,7 +824,6 @@ bool BiffWorksheetFragment::importFragment()
|
|||
case BIFF_ID_COLUMNDEFAULT: importColumnDefault(); break;
|
||||
case BIFF_ID_COLWIDTH: importColWidth(); break;
|
||||
case BIFF2_ID_DEFROWHEIGHT: importDefRowHeight(); break;
|
||||
case BIFF_ID_NOTE: importNote(); break;
|
||||
case BIFF2_ID_WINDOW2: rSheetViewSett.importWindow2( mrStrm ); break;
|
||||
}
|
||||
break;
|
||||
|
@ -834,7 +834,6 @@ bool BiffWorksheetFragment::importFragment()
|
|||
case BIFF_ID_DEFCOLWIDTH: importDefColWidth(); break;
|
||||
case BIFF3_ID_DEFROWHEIGHT: importDefRowHeight(); break;
|
||||
case BIFF_ID_HCENTER: rPageSett.importHorCenter( mrStrm ); break;
|
||||
case BIFF_ID_NOTE: importNote(); break;
|
||||
case BIFF_ID_OBJ: rDrawing.importObj( mrStrm ); break;
|
||||
case BIFF_ID_OBJECTPROTECT: rWorksheetSett.importObjectProtect( mrStrm ); break;
|
||||
case BIFF_ID_SAVERECALC: rWorkbookSett.importSaveRecalc( mrStrm ); break;
|
||||
|
@ -851,7 +850,6 @@ bool BiffWorksheetFragment::importFragment()
|
|||
case BIFF_ID_COLINFO: importColInfo(); break;
|
||||
case BIFF3_ID_DEFROWHEIGHT: importDefRowHeight(); break;
|
||||
case BIFF_ID_HCENTER: rPageSett.importHorCenter( mrStrm ); break;
|
||||
case BIFF_ID_NOTE: importNote(); break;
|
||||
case BIFF_ID_OBJ: rDrawing.importObj( mrStrm ); break;
|
||||
case BIFF_ID_OBJECTPROTECT: rWorksheetSett.importObjectProtect( mrStrm ); break;
|
||||
case BIFF_ID_PAGESETUP: rPageSett.importPageSetup( mrStrm ); break;
|
||||
|
@ -870,7 +868,6 @@ bool BiffWorksheetFragment::importFragment()
|
|||
case BIFF3_ID_DEFROWHEIGHT: importDefRowHeight(); break;
|
||||
case BIFF_ID_HCENTER: rPageSett.importHorCenter( mrStrm ); break;
|
||||
case BIFF_ID_MERGEDCELLS: importMergedCells(); break; // #i62300# also in BIFF5
|
||||
case BIFF_ID_NOTE: importNote(); break;
|
||||
case BIFF_ID_OBJ: rDrawing.importObj( mrStrm ); break;
|
||||
case BIFF_ID_OBJECTPROTECT: rWorksheetSett.importObjectProtect( mrStrm ); break;
|
||||
case BIFF_ID_PAGESETUP: rPageSett.importPageSetup( mrStrm ); break;
|
||||
|
|
Loading…
Reference in a new issue