Hello pyRevit friends
I have a bunch of buttons that have very similar code and I´m tired of debugging and making changes multiple times.
So I started to use the exact same script for every button, the logic of the script is driven by the button name, script.get_bundle_name()
So far so good, but copying the script to multiple folders after every change is also annoying.
So the next step to make this more convenient would be to just call the same code file from every button.
But I don´t know how I can do this, should I put the whole code inside a function and use that as a library?
Thankful for any advice!
Kind regards
code:
# -*- coding: utf-8 -*-
# Native and Third-Party Imports
import os
from datetime import datetime
from os.path import exists
from os import remove
# .NET imports
import clr
import System
clr.AddReference("RevitAPI")
clr.AddReference("RevitServices")
clr.AddReference('RevitAPIUI')
# Revit and RevitServices Imports
from Autodesk.Revit import DB
from Autodesk.Revit.DB import (ElementId, BuiltInCategory, BuiltInParameter, FilteredElementCollector, PrintSetting, ViewSheetSet, PrintManager, ViewSet, Transaction)
from Autodesk.Revit.UI import (TaskDialog, TaskDialogCommonButtons, TaskDialogResult, TaskDialogCommandLinkId, TaskDialogIcon)
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
# PyRevit Imports
from pyrevit import forms
from pyrevit import script
import Log
# Variables for Active Document and Application
uidoc = __revit__.ActiveUIDocument
doc = __revit__.ActiveUIDocument.Document
app = __revit__.Application
def create_print_folder():
path = "C:\\Print"
try:
if not exists(path):
os.mkdir(path)
except Exception as e:
TaskDialog.Show('Error', "Failed to create directory: {}".format(e))
def create_temp_print_settings():
outlist = []
for size, string in zip(PAPER_SIZE_ELEMENTS,PAPER_SIZE_STRINGS):
tempPrintSettingName = "tempPrintSetting_" + string
PrintParameters = PRINT_MANAGER.PrintSetup.CurrentPrintSetting.PrintParameters
processing_type = get_processing_type()
PrintParameters.PaperSize = size
PrintParameters.ZoomType = PrintParameters.ZoomType.Zoom
PRINT_MANAGER.PrintSetup.CurrentPrintSetting.PrintParameters.Zoom = 100
#PrintParameters.ZoomType = PrintParameters.ZoomType.FitToPage
PrintParameters.PageOrientation = PrintParameters.PageOrientation.Landscape
#PrintParameters.PageOrientation = PrintParameters.PageOrientation.Portrait
PrintParameters.ViewLinksinBlue = False
PrintParameters.HideReforWorkPlanes = True
PrintParameters.HideUnreferencedViewTags = True
PrintParameters.MaskCoincidentLines = True
PrintParameters.HideScopeBoxes = True
PrintParameters.HideCropBoundaries = True
PrintParameters.ReplaceHalftoneWithThinLines = True
PrintParameters.ColorDepth = PrintParameters.ColorDepth.Color
#PrintParameters.ColorDepth = PrintParameters.ColorDepth.GrayScale
#PrintParameters.ColorDepth = PrintParameters.ColorDepth.BlackLine
if processing_type == "Raster":
PrintParameters.HiddenLineViews = PrintParameters.HiddenLineViews.RasterProcessing
#print "Raster"
else:
PrintParameters.HiddenLineViews = PrintParameters.HiddenLineViews.VectorProcessing
#print "Vector"
#PrintParameters.RasterQuality = PrintParameters.RasterQuality.High
#PrintParameters.RasterQuality = PrintParameters.RasterQuality.Low
#PrintParameters.RasterQuality = PrintParameters.RasterQuality.Medium
PrintParameters.RasterQuality = PrintParameters.RasterQuality.Presentation
#PrintParameters.PaperPlacement = PrintParameters.PaperPlacement.Center
PrintParameters.PaperPlacement = PrintParameters.PaperPlacement.LowerLeft
PrintParameters.MarginType = PrintParameters.MarginType.NoMargin
#PrintParameters.MarginType = PrintParameters.MarginType.PrinterLimit
#PrintParameters.MarginType = PrintParameters.MarginType.UserDefined
PRINT_MANAGER.PrintSetup.SaveAs(tempPrintSettingName)
PRINT_MANAGER.Apply()
outlist.append(tempPrintSettingName)
return outlist
def print_view(doc, sheet, pRange, printerName, combined, filePath, printSetting):
# Create a set of views and insert the given sheet
view_set = ViewSet()
view_set.Insert(sheet)
# Make the newly created view set the current one
view_sheet_setting = PRINT_MANAGER.ViewSheetSetting
view_sheet_setting.CurrentViewSheetSet.Views = view_set
# Configure print manager settings for virtual printers
if PRINT_MANAGER.IsVirtual:
PRINT_MANAGER.CombinedFile = combined
PRINT_MANAGER.PrintToFile = True
PRINT_MANAGER.PrintToFileName = filePath
# Delete existing file to avoid override prompts
if exists(filePath):
try:
remove(filePath)
except:
user_message("File is open in another application", "Close the PDF before printing")
# Set and apply print settings
try:
print_setup = PRINT_MANAGER.PrintSetup
print_setup.CurrentPrintSetting = printSetting
except Exception as e:
TaskDialog.Show('Error', "Failed to set print settings: {}".format(e))
# Save settings, submit the print job, and clean up
view_sheet_setting.SaveAs("tempSetName")
PRINT_MANAGER.Apply()
PRINT_MANAGER.SubmitPrint()
view_sheet_setting.Delete()
def get_active_sheet():
active_view = doc.ActiveView
if active_view.Category.Id == ElementId(BuiltInCategory.OST_Sheets):
return [active_view]
return []
def create_file_paths():
outlist=[]
for sheet in SHEETS:
sheetname = sheet.Name
sheetnumber = sheet.SheetNumber
RevitFileName = doc.Title
if RevitFileName == "_BIM360_R2022":
Ausgabe = sheet.LookupParameter("9. AUSGABE DOK.NR").AsString()
Version = sheet.LookupParameter("9.1 VERSION DOK.NR").AsString()
filepath = "C:\\Print\\"+sheetnumber+"-"+Ausgabe+"_"+Version+".pdf"
else:
filepath = "C:\\Print\\"+sheetnumber+"-"+sheetname+".pdf"
outlist.append(filepath)
return outlist
def delete_old_print_settings():
ids_to_delete = []
# First, collect the IDs of the settings you want to delete
try:
for setting in ALL_PRINT_SETTINGS:
if "tempPrintSetting_" in setting.Name:
ids_to_delete.append(setting.Id)
except Exception as e:
TaskDialog.Show("Error Collecting Print Settings", "Error collecting temp print settings for deletion: {}".format(e))
return
# Now, delete the settings using the collected IDs
try:
for setting_id in ids_to_delete:
doc.Delete(setting_id)
except Exception as e:
TaskDialog.Show("Error Deleting Print Settings", "Error deleting temp print settings: {}".format(e))
def set_vorpause():
# Filter sheets that have the "VORPAUSE" parameter
sheets_to_update = [sheet for sheet in SHEETS if sheet.LookupParameter("VORPAUSE")]
# If there are no sheets to update, exit
if not sheets_to_update:
return
# Start the transaction
transaction = Transaction(doc, 'Set Vorpause')
try:
transaction.Start()
for sheet in sheets_to_update:
vorpause_para = sheet.LookupParameter("VORPAUSE")
if vorpause_para:
if "Vorpause" in BUNDLE_NAME:
VorpauseValue = "VORPAUSE " + Date
vorpause_para.Set(VorpauseValue)
else:
vorpause_para.Set(" ")
transaction.Commit()
except Exception as e:
# If there's an error, roll back the transaction and show a TaskDialog
transaction.RollBack()
TaskDialog.Show("Error", "Failed to set VORPAUSE parameter: {}".format(e))
def get_paper_size():
paper_size_strings = []
paper_size_elements =[]
size_errors=[]
for sheet in SHEETS:
first_ttbl = FilteredElementCollector(doc,sheet.Id).OfCategory(BuiltInCategory.OST_TitleBlocks).FirstElement()
if first_ttbl:
width = first_ttbl.get_Parameter(BuiltInParameter.SHEET_WIDTH).AsDouble() * 0.3048
# Compare the width value with tolerance
if abs(width - 1.19) < 1e-3:
size = "A0"
elif abs(width - 0.84) < 1e-3:
size = "A1"
elif abs(width - 0.59) < 1e-3:
size = "A2"
elif abs(width - 0.42) < 1e-3:
size = "A3"
else:
size = "A0"
size_errors.append("Size not found. A0 was used instead.")
paper_size_strings.append(size)
else:
size_errors.append("No Title Block found on the Sheet.")
if paper_size_strings:
for i in paper_size_strings :
for x in PRINT_MANAGER.PaperSizes:
if i == x.Name:
paper_size = x
paper_size_elements.append(paper_size)
break # exit inner loop once match is found
return paper_size_elements, paper_size_strings , size_errors
def collect_print_settings():
outlist = []
for cps in TEMP_PRINT_SETTINGS:
for aps in ALL_PRINT_SETTINGS:
if aps.Name == cps:
print_setting = aps
outlist.append(print_setting)
break
return outlist
def delete_view_sets():
try:
view_sets = FilteredElementCollector(doc).OfClass(ViewSheetSet)
ids_to_delete = [i.Id for i in view_sets if i.Name == "tempSetName"]
for view_set_id in ids_to_delete:
doc.Delete(view_set_id)
except Exception as e:
TaskDialog.Show('Error', "An error occurred: {}".format(e))
def delete_print_settings():
ids_to_delete = []
# First, collect the IDs of the print settings you want to delete
try:
for print_setting in PRINT_SETTINGS:
ids_to_delete.append(print_setting.Id)
except Exception as e:
TaskDialog.Show('Error', "An error occurred while collecting print settings for deletion: {}".format(e))
return
# Now, delete the print settings using the collected IDs
try:
for setting_id in ids_to_delete:
doc.Delete(setting_id)
except Exception as e:
TaskDialog.Show('Error', "An error occurred while deleting print settings: {}".format(e))
def user_message(line1,line2):
taskDialog = TaskDialog("Results")
taskDialog.MainInstruction = line1
taskDialog.MainContent = line2
taskDialog.TitleAutoPrefix = False
taskDialog.MainIcon = TaskDialogIcon.TaskDialogIconInformation
taskDialog.CommonButtons = TaskDialogCommonButtons.Close #| TaskDialogCommonButtons.Yes
#taskDialog.FooterText = "Help"
return taskDialog.Show()
def get_processing_type():
try:
pdf_config = script.get_config("PDFsetting")
processing_option = pdf_config.get_option('hidden_lines_processing')
return processing_option
except Exception as e:
TaskDialog.Show('Error', "An error occurred while fetching the processing type: {}".format(e))
return None
def get_sheet_set():
active_sheet = None
# Check if the ActiveView's category is 'OST_Sheets'.
if ACTIVE_VIEW.Category.Id == ElementId(BuiltInCategory.OST_Sheets):
active_sheet = ACTIVE_VIEW
# If an Active Sheet is found, get its parameters.
if active_sheet:
para = active_sheet.GetParameters(BrowserSortParameter)
if para:
# Assuming there's only one parameter value we care about.
paravalue = para[0].AsValueString()
else:
paravalue = None
# If we found a parameter value, use it to filter sheets.
if paravalue:
provider = ParameterValueProvider(para[0].Id)
evaluator = FilterStringContains()
rule = FilterStringRule(provider, evaluator, paravalue)
filter = ElementParameterFilter(rule)
sheet_set = FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Sheets).WherePasses(filter).ToElements()
else:
sheet_set = []
return sheet_set
def get_open_sheets():
outlist = []
uiviews = uidoc.GetOpenUIViews()
for uiview in uiviews:
view = doc.GetElement(uiview.ViewId)
if view.Category.Name == "Sheets" and view.Name != "None":
outlist.append(view)
sorted_elements = sorted(outlist, key=lambda x: x.SheetNumber)
return sorted_elements
def get_sheet_number(sheet):
return sheet.get_Parameter(BuiltInParameter.SHEET_NUMBER).AsString()
def get_all_sheets():
sheets = FilteredElementCollector(doc).OfClass(ViewSheet).ToElements()
sorted_sheets = sorted(sheets, key=get_sheet_number)
return sorted_sheets
def get_sheet_set_names():
outlist = []
if BrowserSortParameter:
for s in ALL_SHEETS:
paravalue = s.LookupParameter(BrowserSortParameter).AsString()
if paravalue not in outlist and paravalue != None:
outlist.append(paravalue)
return outlist
def get_sheets_by_sheet_set():
outlist = []
for name in SHEET_SET_NAMES:
outlist2 = []
for sheet in ALL_SHEETS:
paravalue = sheet.LookupParameter(BrowserSortParameter).AsString()
if paravalue == name:
outlist2.append(sheet)
outlist.append(outlist2)
return outlist
def add_open_sheets():
if OPEN_SHEETS:
SHEET_SET_NAMES.insert(0,"0_Open")
SHEETS_BY_SHEET_SET.insert(0,OPEN_SHEETS)
return SHEET_SET_NAMES, SHEETS_BY_SHEET_SET
class MyOptionSheet(forms.TemplateListItem):
@property
def name(self):
return '{} - {}'.format(
self.item.SheetNumber,
self.item.Name)
def natural_sort_key(key):
return [int(c) if c.isdigit() else c.lower() for c in re.split('(\d+)', key)]
def select_sheets():
ops = {}
AllSheets = []
AllSheets.extend([MyOptionSheet(x) for x in ALL_SHEETS if not x.IsPlaceholder])
ops['1_All'] = AllSheets
for name, sheets in zip(SHEET_SET_NAMES,SHEETS_BY_SHEET_SET):
sheets = []
for sheet in sheets:
sheets.append(MyOptionSheet(sheet))
ops[name] = sheets
sorted_ops = OrderedDict(sorted(ops.items(), key=lambda x: natural_sort_key(x[0])))
if OPEN_SHEETS:
selection = forms.SelectFromList.show(sorted_ops, 'Print Sheets PDF', group_selector_title='Sheet Sets', default_group= '0_Open', multiselect=True)
else:
selection = forms.SelectFromList.show(sorted_ops, 'Print Sheets PDF', group_selector_title='Sheet Sets', default_group= '1_All', multiselect=True)
return selection
# Get bundle Name
BUNDLE_NAME = script.get_bundle_name()
# Get the current date
now = datetime.now()
DATE_FORMAT = "%d.%m.%Y"
date = now.strftime(DATE_FORMAT)
# Initial setup
PRINTER_NAME = "PDF-XChange Standard"
create_print_folder()
FILE_PATHS = create_file_paths()
SIZE_ERRORS = None
ACTIVE_VIEW = doc.ActiveView
if "Active" in BUNDLE_NAME:
SHEETS = get_active_sheet()
elif "Set" in BUNDLE_NAME:
SHEETS = get_sheet_set()
elif "Select" in BUNDLE_NAME:
OPEN_SHEETS = get_open_sheets()
ALL_SHEETS = get_all_sheets()
SheetSetNames = get_sheet_set_names()
SHEETS_BY_SHEET_SET = get_sheets_by_sheet_set()
SHEETS = select_sheets()
SHEET_SET_NAMES, SHEETS_BY_SHEET_SET = add_open_sheets()
if SHEETS and FILE_PATHS:
ALL_PRINT_SETTINGS = FilteredElementCollector(doc).OfClass(PrintSetting)
set_vorpause()
t = Transaction(doc, 'Print PDF')
t.Start()
delete_view_sets()
delete_old_print_settings()
PRINT_MANAGER = doc.PrintManager
PRINT_MANAGER.SelectNewPrintDriver(PRINTER_NAME)
p_range = System.Enum.Parse(DB.PrintRange, "Select")
combined = True
PRINT_MANAGER.PrintRange = p_range
PRINT_MANAGER.Apply()
PAPER_SIZE_ELEMENTS, PAPER_SIZE_STRINGS, SIZE_ERRORS = get_paper_size()
TEMP_PRINT_SETTINGS = create_temp_print_settings()
PRINT_SETTINGS = collect_print_settings()
if PRINT_SETTINGS:
try:
for sheet, print_setting, file_path in zip(SHEETS, PRINT_SETTINGS, FILE_PATHS):
print_view(doc, sheet, p_range, PRINTER_NAME, combined, file_path, print_setting)
except Exception as e:
t.RollBack()
user_message("Error", "An error occurred during printing: {}".format(e))
else:
delete_print_settings()
t.Commit()
os.startfile("C:\Print")
else:
t.RollBack()
user_message("Error", "An error occurred when creating the print settings")
if not SHEETS:
user_message("No active Sheet", "A Sheet has to be active before running")
if SIZE_ERRORS:
user_message("Error at getting the Paper Size", SIZE_ERRORS[0])
Log.LOG_Entry()
Log.Read_LOG()
Log.Write_LOG()