"""
The ``export`` submodule hosts all classes related to sheet export such as **DWG** and **PDF**.
For example sending the currently active sheet to a PDF printer in the network works as follows::
exporter = revitron.PDFExporter(printerAddress, printerPath)
exporter.printSheet(revitron.ACTIVE_VIEW,
'A0',
'Landscape',
'C:/pdf',
'{Sheet Number}-{Sheet Title}')
Please check out the
`export tool <https://github.com/revitron/revitron-ui/blob/master/Revitron.tab/Revitron.panel/Export.pulldown/Export%20Sheets%20as%20PDF.pushbutton/Export%20Sheets%20as%20PDF_script.py>`_
of the **Revitron UI** extension to learn how to export a selection of sheets
with a felxible configuration stored in a document.
"""
#-*- coding: UTF-8 -*-
import os, shutil, time, sys, glob, re
from pyrevit import script
from System.Collections.Generic import List
[docs]class CSVExporter:
"""
Export a schedule as CSV named by a file naming template.
"""
[docs] def __init__(self):
"""
Inits a new CSVExporter instance.
"""
pass
[docs] def exportSchedule(
self, schedule, directory, template=False, delimiter=';', hasTitle=False
):
"""
Exports a schedule.
Args:
schedule (object): A Revit schedule
directory (string): A custom output directory. Defaults to False.
template (string, optional): A name template. Defaults to '{View Name}'.
delimiter (string, optional): A csv delimiter. Defaults to ';'.
hasTitle (bool, optional): Set True to export schedule title. Defaults to False.
Returns:
string: The path of the exported CSV. False on error.
"""
import revitron
if revitron.Element(schedule).getClassName() != 'ViewSchedule':
revitron.Log().warning('Element is not a schedule!')
return False
if not directory:
revitron.Log().warning('No directory specified!')
return False
if not template:
template = '{View Name}'
name = revitron.ParameterTemplate(schedule, template).render() + '.csv'
if not os.path.exists(directory):
os.makedirs(directory)
options = revitron.DB.ViewScheduleExportOptions()
options.FieldDelimiter = delimiter
options.Title = hasTitle
options.TextQualifier = revitron.DB.ExportTextQualifier['None']
schedule.Export(directory, name, options)
file = os.path.join(directory, name)
return file
[docs]class DWGExporter:
"""
Export sheets as DWG named by a file naming template.
"""
[docs] def __init__(self, setupName):
"""
Inits a new DWGExporter instance.
Args:
setupName (string): The name of a stored export setup
"""
import revitron
self.options = revitron.DB.DWGExportOptions().GetPredefinedOptions(
revitron.DOC, setupName
)
[docs] def exportSheet(self, sheet, directory, unit, template=False):
"""
Exports a sheet.
Args:
sheet (object): A Revit sheet
directory (string): The export directory
unit (object): The `export unit <https://www.revitapidocs.com/2020/1d3eb4f4-81d2-10a6-3eab-4a9c20e39053.htm>`_
template (string, optional): A name template. Defaults to '{Sheet Number}-{Sheet Name}'.
Returns:
string: The path of the exported PDF. False on error.
"""
import revitron
if revitron.Element(sheet).getClassName() != 'ViewSheet':
revitron.Log().warning('Element is not a sheet!')
return False
if not directory:
revitron.Log().warning('There is no DWG export directory defined!')
sys.exit()
if not template:
template = '{Sheet Number}-{Sheet Name}'
fullPath = os.path.join(
directory, revitron.ParameterTemplate(sheet, template).render() + '.dwg'
)
path = os.path.dirname(fullPath)
file = os.path.basename(fullPath)
if not os.path.exists(path):
os.makedirs(path)
db = revitron.DB
self.options.MergedViews = True
self.options.TargetUnit = unit
success = revitron.DOC.Export(
path, file, List[db.ElementId]([sheet.Id]), self.options
)
if success:
return fullPath
return False
[docs]class PDFExporter:
"""
Export sheets as PDF named by a file naming template.
"""
[docs] def __init__(self, printer, output):
"""
Inits a new PDFExporter instance.
Args:
printer (string): The printer network adress
output (string): The printer output directory
"""
import revitron
if not printer or not output:
revitron.Log().warning('PDF exporter is not configured!')
sys.exit()
self.printer = printer
self.output = output
self.manager = revitron.DOC.PrintManager
self.sizes = dict()
if self.manager.PrinterName.lower() != self.printer.lower():
print('Setting current printer to: ' + self.printer)
print('Please submit your sheets to be exported again ...')
self.manager.SelectNewPrintDriver(self.printer)
self.manager.Apply()
sys.exit()
self.manager.PrintRange = revitron.DB.PrintRange.Select
self.manager.PrintToFile = True
self.manager.CombinedFile = False
self.manager.Apply()
for size in self.manager.PaperSizes:
self.sizes[size.Name] = size
[docs] def printSheet(
self,
sheet,
size,
orientation='Landscape',
colorMode='Color',
directory=False,
template=False
):
"""
Prints a sheet.
Args:
sheet (object): A Revit sheet
size (string): A size name like A0 or A4
orientation (string, optional): The orientation, 'Landscape' or 'Portrait'. Defaults to 'Landscape'.
colorMode (string, optional): The color setting for the printed sheets. Defaults to 'Color'.
directory (string, optional): A custom output directory. Defaults to False.
template (string, optional): A name template. Defaults to '{Sheet Number}-{Sheet Name}'.
Returns:
string: The path of the exported PDF. False on error.
"""
import revitron
if revitron.Element(sheet).getClassName() != 'ViewSheet':
revitron.Log().warning('Element is not a sheet!')
return False
if not colorMode:
colorMode = 'Color'
if not directory:
directory = self.output
if not template:
template = '{Sheet Number}-{Sheet Name}'
path = os.path.join(
directory, revitron.ParameterTemplate(sheet, template).render() + '.pdf'
)
if not os.path.exists(os.path.dirname(path)):
os.makedirs(os.path.dirname(path))
transaction = revitron.Transaction()
viewSet = revitron.DB.ViewSet()
viewSet.Insert(sheet)
viewSheetSetting = self.manager.ViewSheetSetting
viewSheetSetting.CurrentViewSheetSet.Views = viewSet
viewSheetSetting.SaveAs("_temp_")
self.manager.PrintSetup.SaveAs("_temp_")
self.manager.Apply()
orientation = getattr(revitron.DB.PageOrientationType, orientation)
# Set current print page settings.
printParameters = self.manager.PrintSetup.CurrentPrintSetting.PrintParameters
printParameters.ZoomType = revitron.DB.ZoomType.Zoom
printParameters.Zoom = 100
printParameters.PaperPlacement = revitron.DB.PaperPlacementType.Center
printParameters.PageOrientation = orientation
printParameters.PaperSize = self.sizes[size]
printParameters.RasterQuality = revitron.DB.RasterQualityType.High
printParameters.ColorDepth = getattr(revitron.DB.ColorDepthType, colorMode)
# Set in-session print settings.
printParameters = self.manager.PrintSetup.InSession.PrintParameters
printParameters.ZoomType = revitron.DB.ZoomType.Zoom
printParameters.Zoom = 100
printParameters.PaperPlacement = revitron.DB.PaperPlacementType.Center
printParameters.PageOrientation = orientation
printParameters.PaperSize = self.sizes[size]
printParameters.RasterQuality = revitron.DB.RasterQualityType.High
printParameters.ColorDepth = getattr(revitron.DB.ColorDepthType, colorMode)
# Again save settings.
try:
self.manager.PrintSetup.Save()
except:
self.manager.PrintSetup.SaveAs("_temp2_")
self.manager.Apply()
self.manager.SubmitPrint(sheet)
viewSheetSetting.Delete()
transaction.rollback()
# Move file form temp output to directory.
timePassed = time.time()
moved = False
while (time.time() - timePassed) < 30 and not moved:
time.sleep(0.5)
tempFiles = glob.glob(self.tempOutputPattern(sheet))
if tempFiles:
tempFile = tempFiles[0]
time.sleep(2)
if os.access(tempFile, os.W_OK):
try:
shutil.move(tempFile, path)
moved = True
except:
pass
if moved:
return path
return False
[docs] def tempOutputPattern(self, sheet):
"""
Create a glob pattern to identify a printed PDF in the system output directory to be able to
move it to its correct location and rename it according to the given template.
Please note that the PDF network printer has to be configured to save PDFs following the below naming scheme::
[Revit File] - Sheet - [Sheet Number] - [Sheet Name].pdf
For example::
Project1 - Sheet - A101 - Unnamed.pdf
Args:
sheet (object): A Revit sheet objetc
Returns:
string: The generated glob pattern
"""
import revitron
nr = re.sub(r'[^a-zA-Z0-9]+', '*', revitron.Element(sheet).get('Sheet Number'))
name = re.sub(r'[^a-zA-Z0-9]+', '*', revitron.Element(sheet).get('Sheet Name'))
printToFileName = re.sub(
r'\.pdf$', '', os.path.basename(self.manager.PrintToFileName)
)
return '{}/{}*Sheet*{}*{}*.pdf'.format(self.output, printToFileName, nr, name)