1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 #include "vbapagebreaks.hxx" 28 #include "vbapagebreak.hxx" 29 #include <ooo/vba/excel/XWorksheet.hpp> 30 using namespace ::com::sun::star; 31 using namespace ::ooo::vba; 32 33 typedef ::cppu::WeakImplHelper1<container::XIndexAccess > RangePageBreaks_Base; 34 class RangePageBreaks : public RangePageBreaks_Base 35 { 36 private: 37 uno::Reference< XHelperInterface > mxParent; 38 uno::Reference< uno::XComponentContext > mxContext; 39 uno::Reference< sheet::XSheetPageBreak > mxSheetPageBreak; 40 sal_Bool m_bColumn; 41 42 public: 43 RangePageBreaks( const uno::Reference< XHelperInterface >& xParent, 44 const uno::Reference< uno::XComponentContext >& xContext, 45 uno::Reference< sheet::XSheetPageBreak >& xSheetPageBreak, 46 sal_Bool bColumn ) : mxParent( xParent ), mxContext( xContext ), mxSheetPageBreak( xSheetPageBreak ), m_bColumn( bColumn ) 47 { 48 } 49 50 sal_Int32 getAPIStartofRange( const uno::Reference< excel::XRange >& xRange ) throw (css::uno::RuntimeException) 51 { 52 if( m_bColumn ) 53 return xRange->getColumn() - 1; 54 return xRange->getRow() - 1; 55 } 56 57 sal_Int32 getAPIEndIndexofRange( const uno::Reference< excel::XRange >& xRange, sal_Int32 nUsedStart ) throw (uno::RuntimeException) 58 { 59 if( m_bColumn ) 60 return nUsedStart + xRange->Columns( uno::Any() )->getCount(); 61 return nUsedStart + xRange->Rows( uno::Any() )->getCount(); 62 } 63 64 uno::Sequence<sheet::TablePageBreakData> getAllPageBreaks() throw (uno::RuntimeException) 65 { 66 if( m_bColumn ) 67 return mxSheetPageBreak->getColumnPageBreaks(); 68 return mxSheetPageBreak->getRowPageBreaks(); 69 } 70 71 uno::Reference<container::XIndexAccess> getRowColContainer() throw (uno::RuntimeException) 72 { 73 uno::Reference< table::XColumnRowRange > xColumnRowRange( mxSheetPageBreak, uno::UNO_QUERY_THROW ); 74 uno::Reference<container::XIndexAccess> xIndexAccess; 75 if( m_bColumn ) 76 xIndexAccess.set( xColumnRowRange->getColumns(), uno::UNO_QUERY_THROW ); 77 else 78 xIndexAccess.set( xColumnRowRange->getRows(), uno::UNO_QUERY_THROW ); 79 return xIndexAccess; 80 } 81 82 sheet::TablePageBreakData getTablePageBreakData( sal_Int32 nAPIItemIndex ) throw ( script::BasicErrorException, uno::RuntimeException); 83 uno::Any Add( const css::uno::Any& Before ) throw ( css::script::BasicErrorException, css::uno::RuntimeException); 84 85 // XIndexAccess 86 virtual sal_Int32 SAL_CALL getCount( ) throw (uno::RuntimeException); 87 virtual uno::Any SAL_CALL getByIndex( sal_Int32 Index ) throw (lang::IndexOutOfBoundsException, lang::WrappedTargetException, uno::RuntimeException); 88 virtual uno::Type SAL_CALL getElementType( ) throw (uno::RuntimeException) 89 { 90 if( m_bColumn ) 91 return excel::XVPageBreak::static_type(0); 92 return excel::XHPageBreak::static_type(0); 93 } 94 virtual sal_Bool SAL_CALL hasElements( ) throw (uno::RuntimeException) 95 { 96 return sal_True; 97 } 98 }; 99 100 /** @TODO Unlike MS Excel this method only considers the pagebreaks that intersect the used range 101 * To become completely compatible the print area has to be considered. As far as I found out this printarea 102 * also considers the position and sizes of shapes and manually inserted page breaks 103 * Note: In MS there is a limit of 1026 horizontal page breaks per sheet. 104 */ 105 sal_Int32 SAL_CALL RangePageBreaks::getCount( ) throw (uno::RuntimeException) 106 { 107 sal_Int32 nCount = 0; 108 uno::Reference< excel::XWorksheet > xWorksheet( mxParent, uno::UNO_QUERY_THROW ); 109 uno::Reference< excel::XRange > xRange = xWorksheet->getUsedRange(); 110 sal_Int32 nUsedStart = getAPIStartofRange( xRange ); 111 sal_Int32 nUsedEnd = getAPIEndIndexofRange( xRange, nUsedStart ); 112 uno::Sequence<sheet::TablePageBreakData> aTablePageBreakData = getAllPageBreaks(); 113 114 sal_Int32 nLength = aTablePageBreakData.getLength(); 115 for( sal_Int32 i=0; i<nLength; i++ ) 116 { 117 sal_Int32 nPos = aTablePageBreakData[i].Position; 118 if( nPos > nUsedEnd ) 119 return nCount; 120 if( nPos >= nUsedStart ) 121 nCount++; 122 } 123 124 return nCount; 125 } 126 127 uno::Any SAL_CALL RangePageBreaks::getByIndex( sal_Int32 Index ) throw (lang::IndexOutOfBoundsException, lang::WrappedTargetException, uno::RuntimeException) 128 { 129 if( (Index < getCount()) && ( Index >= 0 )) 130 { 131 sheet::TablePageBreakData aTablePageBreakData = getTablePageBreakData( Index ); 132 uno::Reference< container::XIndexAccess > xIndexAccess = getRowColContainer(); 133 sal_Int32 nPos = aTablePageBreakData.Position; 134 if( (nPos < xIndexAccess->getCount()) && (nPos > -1) ) 135 { 136 uno::Reference< beans::XPropertySet > xRowColPropertySet( xIndexAccess->getByIndex(nPos), uno::UNO_QUERY_THROW ); 137 if( m_bColumn ) 138 return uno::makeAny( uno::Reference< excel::XVPageBreak >( new ScVbaVPageBreak( mxParent, mxContext, xRowColPropertySet, aTablePageBreakData) )); 139 return uno::makeAny( uno::Reference< excel::XHPageBreak >( new ScVbaHPageBreak( mxParent, mxContext, xRowColPropertySet, aTablePageBreakData) )); 140 } 141 } 142 throw lang::IndexOutOfBoundsException(); 143 } 144 145 sheet::TablePageBreakData RangePageBreaks::getTablePageBreakData( sal_Int32 nAPIItemIndex ) throw ( script::BasicErrorException, uno::RuntimeException) 146 { 147 sal_Int32 index = -1; 148 sheet::TablePageBreakData aTablePageBreakData; 149 uno::Reference< excel::XWorksheet > xWorksheet( mxParent, uno::UNO_QUERY_THROW ); 150 uno::Reference< excel::XRange > xRange = xWorksheet->getUsedRange(); 151 sal_Int32 nUsedStart = getAPIStartofRange( xRange ); 152 sal_Int32 nUsedEnd = getAPIEndIndexofRange( xRange, nUsedStart ); 153 uno::Sequence<sheet::TablePageBreakData> aTablePageBreakDataList = getAllPageBreaks(); 154 155 sal_Int32 nLength = aTablePageBreakDataList.getLength(); 156 for( sal_Int32 i=0; i<nLength; i++ ) 157 { 158 aTablePageBreakData = aTablePageBreakDataList[i]; 159 sal_Int32 nPos = aTablePageBreakData.Position; 160 if( nPos >= nUsedStart ) 161 index++; 162 if( nPos > nUsedEnd ) 163 DebugHelper::exception(SbERR_METHOD_FAILED, rtl::OUString()); 164 if( index == nAPIItemIndex ) 165 return aTablePageBreakData; 166 } 167 168 return aTablePageBreakData; 169 } 170 171 uno::Any RangePageBreaks::Add( const css::uno::Any& Before ) throw ( css::script::BasicErrorException, css::uno::RuntimeException) 172 { 173 uno::Reference< excel::XRange > xRange; 174 Before >>= xRange; 175 if( !xRange.is() ) 176 { 177 DebugHelper::exception(SbERR_BAD_ARGUMENT, rtl::OUString()); 178 } 179 180 sal_Int32 nAPIRowColIndex = getAPIStartofRange( xRange ); 181 uno::Reference< container::XIndexAccess > xIndexAccess = getRowColContainer(); 182 uno::Reference< beans::XPropertySet > xRowColPropertySet( xIndexAccess->getByIndex(nAPIRowColIndex), uno::UNO_QUERY_THROW ); 183 xRowColPropertySet->setPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsStartOfNewPage" )), uno::makeAny(sal_True)); 184 sheet::TablePageBreakData aTablePageBreakData; 185 aTablePageBreakData.ManualBreak = sal_True; 186 aTablePageBreakData.Position = nAPIRowColIndex; 187 if( m_bColumn ) 188 return uno::makeAny( uno::Reference< excel::XVPageBreak >( new ScVbaVPageBreak( mxParent, mxContext, xRowColPropertySet, aTablePageBreakData) )); 189 return uno::makeAny( uno::Reference< excel::XHPageBreak >( new ScVbaHPageBreak( mxParent, mxContext, xRowColPropertySet, aTablePageBreakData) )); 190 } 191 192 193 class RangePageBreaksEnumWrapper : public EnumerationHelper_BASE 194 { 195 uno::Reference<container::XIndexAccess > m_xIndexAccess; 196 sal_Int32 nIndex; 197 public: 198 RangePageBreaksEnumWrapper( const uno::Reference< container::XIndexAccess >& xIndexAccess ) : m_xIndexAccess( xIndexAccess ), nIndex( 0 ) {} 199 virtual ::sal_Bool SAL_CALL hasMoreElements( ) throw (uno::RuntimeException) 200 { 201 return ( nIndex < m_xIndexAccess->getCount() ); 202 } 203 204 virtual uno::Any SAL_CALL nextElement( ) throw (container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException) 205 { 206 if ( nIndex < m_xIndexAccess->getCount() ) 207 return m_xIndexAccess->getByIndex( nIndex++ ); 208 throw container::NoSuchElementException(); 209 } 210 }; 211 212 ScVbaHPageBreaks::ScVbaHPageBreaks( const uno::Reference< XHelperInterface >& xParent, 213 const uno::Reference< uno::XComponentContext >& xContext, 214 uno::Reference< sheet::XSheetPageBreak >& xSheetPageBreak) throw (uno::RuntimeException): 215 ScVbaHPageBreaks_BASE( xParent,xContext, new RangePageBreaks( xParent, xContext, xSheetPageBreak, sal_False )), 216 mxSheetPageBreak( xSheetPageBreak ) 217 { 218 } 219 220 uno::Any SAL_CALL ScVbaHPageBreaks::Add( const uno::Any& Before) throw ( script::BasicErrorException, uno::RuntimeException) 221 { 222 RangePageBreaks* pPageBreaks = dynamic_cast< RangePageBreaks* >( m_xIndexAccess.get() ); 223 if( pPageBreaks ) 224 { 225 return pPageBreaks->Add( Before ); 226 } 227 return uno::Any(); 228 } 229 230 uno::Reference< container::XEnumeration > 231 ScVbaHPageBreaks::createEnumeration() throw (uno::RuntimeException) 232 { 233 return new RangePageBreaksEnumWrapper( m_xIndexAccess ); 234 } 235 236 uno::Any 237 ScVbaHPageBreaks::createCollectionObject( const css::uno::Any& aSource ) 238 { 239 return aSource; // its already a pagebreak object 240 } 241 242 uno::Type 243 ScVbaHPageBreaks::getElementType() throw (uno::RuntimeException) 244 { 245 return excel::XHPageBreak::static_type(0); 246 } 247 248 rtl::OUString& 249 ScVbaHPageBreaks::getServiceImplName() 250 { 251 static rtl::OUString sImplName( RTL_CONSTASCII_USTRINGPARAM("ScVbaHPageBreaks") ); 252 return sImplName; 253 } 254 255 uno::Sequence< rtl::OUString > 256 ScVbaHPageBreaks::getServiceNames() 257 { 258 static uno::Sequence< rtl::OUString > aServiceNames; 259 if ( aServiceNames.getLength() == 0 ) 260 { 261 aServiceNames.realloc( 1 ); 262 aServiceNames[ 0 ] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("ooo.vba.excel.HPageBreaks" ) ); 263 } 264 return aServiceNames; 265 } 266 267 //VPageBreak 268 ScVbaVPageBreaks::ScVbaVPageBreaks( const uno::Reference< XHelperInterface >& xParent, 269 const uno::Reference< uno::XComponentContext >& xContext, 270 uno::Reference< sheet::XSheetPageBreak >& xSheetPageBreak ) throw ( uno::RuntimeException ) 271 : ScVbaVPageBreaks_BASE( xParent, xContext, new RangePageBreaks( xParent, xContext, xSheetPageBreak, sal_True ) ), 272 mxSheetPageBreak( xSheetPageBreak ) 273 { 274 } 275 276 ScVbaVPageBreaks::~ScVbaVPageBreaks() 277 { 278 } 279 280 uno::Any SAL_CALL 281 ScVbaVPageBreaks::Add( const uno::Any& Before ) throw ( script::BasicErrorException, uno::RuntimeException ) 282 { 283 RangePageBreaks* pPageBreaks = dynamic_cast< RangePageBreaks* >( m_xIndexAccess.get() ); 284 if( pPageBreaks ) 285 { 286 return pPageBreaks->Add( Before ); 287 } 288 return uno::Any(); 289 } 290 291 uno::Reference< container::XEnumeration > 292 ScVbaVPageBreaks::createEnumeration() throw ( uno::RuntimeException ) 293 { 294 return new RangePageBreaksEnumWrapper( m_xIndexAccess ); 295 } 296 297 uno::Any 298 ScVbaVPageBreaks::createCollectionObject( const css::uno::Any& aSource ) 299 { 300 return aSource; // its already a pagebreak object 301 } 302 303 uno::Type 304 ScVbaVPageBreaks::getElementType() throw ( uno::RuntimeException ) 305 { 306 return excel::XVPageBreak::static_type( 0 ); 307 } 308 309 rtl::OUString& 310 ScVbaVPageBreaks::getServiceImplName() 311 { 312 static rtl::OUString sImplName( RTL_CONSTASCII_USTRINGPARAM( "ScVbaVPageBreaks" ) ); 313 return sImplName; 314 } 315 316 uno::Sequence< rtl::OUString > 317 ScVbaVPageBreaks::getServiceNames() 318 { 319 static uno::Sequence< rtl::OUString > aServiceNames; 320 if ( aServiceNames.getLength() == 0 ) 321 { 322 aServiceNames.realloc( 1 ); 323 aServiceNames[ 0 ] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ooo.vba.excel.VPageBreaks" ) ); 324 } 325 return aServiceNames; 326 } 327 328