Jump to content

Neda Roohnia

Member
  • Posts

    25
  • Joined

  • Last visited

Posts posted by Neda Roohnia

  1. I am posting the final version of the code in here in case anyone wanted to have it.

     

    import vs

    # Define a function to list the names of all sheet layers in the current document
    def list_sheet_layer_names():
        layer_names = []
        hLayer = vs.FLayer()

        # Use a while loop and the NextLayer() function to iterate through all the sheet layers in the document
        while hLayer != None:
            layer_names.append(hLayer)
            hLayer = vs.NextLayer(hLayer)

        # Use a lambda function to filter the list of layer names to only include sheet layers
        layer_type = lambda x: vs.GetObjectVariableInt(x, 154)
        layer_names = [vs.GetLName(x) for x in layer_names if layer_type(x) == 2]

        return layer_names

    # Define a function to get the handles of all objects in the current document that meet certain criteria
    def get_objects_from_criteria(criteria):
        object_handles = []
        def get_obj(h):
            object_handles.append(h)

        # Use the ForEachObject() function to iterate through all objects in the document and add their handles to the list if they meet the criteria
        vs.ForEachObject(get_obj, criteria)

        return object_handles

    # Define a function to calculate the area of a given object
    def get_object_area(object):
        top_left, bot_right = vs.GetBBox(object)
        length = bot_right[0] - top_left[0]
        height = top_left[1] - bot_right[1]
        return length * height

    def ImpScale(SF):
        if SF == 12:
            return "1\" = 1'-0\""
        elif SF == 24:
            return "1/2\" = 1'-0\""
        elif SF == 32:
            return "3/8\" = 1'-0\""
        elif SF == 48:
            return "1/4\" = 1'-0\""
        elif SF == 64:
            return "3/16\" = 1'-0\""
        elif SF == 96:
            return "1/8\" = 1'-0\""
        elif SF == 128:
            return "3/32\" = 1'-0\""
        elif SF == 192:
            return "1/16\" = 1'-0\""
        elif SF == 384:
            return "1/32\" = 1'-0\""
        else:
            return f'1:{SF:.0f}'

    def exclude_titleblock(tblocks):
        excluded_blocks = []
        exclude_names = ['Landscape Details', 'Landscape Sections', 'Landscape Cut Sheets']
        for tblock in tblocks:
            record_name = 'Title Block Sheet Data'  # Adjust the record name based on your specific title block record
            field_name = 'Sheet Title'  # Adjust the field name based on your specific title field
            strRecordName = vs.GetRField(tblock, record_name, field_name)
            is_excluded = any(name in strRecordName for name in exclude_names)
            if not is_excluded:
                excluded_blocks.append(tblock)
        return excluded_blocks

    def include_titleblock(tblocks):
        included_blocks = []
        include_names = ['Landscape Details', 'Landscape Sections']
        for tblock in tblocks:
            record_name = 'Title Block Sheet Data'  # Adjust the record name based on your specific title block record
            field_name = 'Sheet Title'  # Adjust the field name based on your specific title field
            strRecordName = vs.GetRField(tblock, record_name, field_name)
            is_included = any(name in strRecordName for name in include_names)
            if is_included:
                included_blocks.append(tblock)
        return included_blocks
        
    def imclude_titleblock(tblocks):
        imcluded_blocks = []
        imclude_names = ['Landscape Cut Sheets', 'Landscape BS']
        for tblock in tblocks:
            record_name = 'Title Block Sheet Data'  # Adjust the record name based on your specific title block record
            field_name = 'Sheet Title'  # Adjust the field name based on your specific title field
            strRecordName = vs.GetRField(tblock, record_name, field_name)
            is_imcluded = any(name in strRecordName for name in imclude_names)
            if is_imcluded:
                imcluded_blocks.append(tblock)
        return imcluded_blocks

    # Iterate through all sheet layers in the current document
    for layer in list_sheet_layer_names():

        # Define criteria strings to find title blocks and viewports on the current layer
        titleblock_crit_str = f"(((L='{layer}') & (PON='Title Block Border')))"
        viewports_crit = f"(((L='{layer}') & (T=VIEWPORT)))"

        # Use the get_objects_from_criteria() function to get lists of title blocks and viewports on the current layer
        titleblocksss = get_objects_from_criteria(titleblock_crit_str)
        titleblocks = exclude_titleblock(titleblocksss)
        viewports = get_objects_from_criteria(viewports_crit)

        # If there is at least one title block and one viewport on the current layer, find the largest viewport and set the scale of the title block to match
        if all([len(titleblocks) > 0, len(viewports) > 0]):
            titleblock = titleblocks[0]  # get single first found only

            vp_area_max = 0.0
            vp_largest = None

            # Iterate through all viewports on the current layer and find the one with the largest area
            for viewport in viewports:
                vp_area = get_object_area(viewport)
                if vp_area > vp_area_max:
                    vp_area_max = vp_area
                    vp_largest = viewport

            # If a largest viewport is found, set the scale of the title block to match
            if vp_largest:
                SF = vs.GetObjectVariableReal(vp_largest, 1003)
                vs.SetRField(titleblock, 'Title Block Sheet Data', 'Scale', ImpScale(SF))
                vs.ResetObject(titleblock)

    # Iterate through all sheet layers in the current document
    for layer in list_sheet_layer_names():

        # Define criteria strings to find title blocks and viewports on the current layer
        titleblock_crit_str = f"(((L='{layer}') & (PON='Title Block Border')))"
        viewports_crit = f"(((L='{layer}') & (T=VIEWPORT)))"

        # Use the get_objects_from_criteria() function to get lists of title blocks and viewports on the current layer
        titleblocksss = get_objects_from_criteria(titleblock_crit_str)
        intitleblocks = include_titleblock(titleblocksss)
        viewports = get_objects_from_criteria(viewports_crit)

        # If there is at least one title block and one viewport on the current layer, find the largest viewport and set the scale of the title block to match
        if all([len(intitleblocks) > 0]):
            titleblock = intitleblocks[0]  # get single first found only
            vs.SetRField(titleblock, 'Title Block Sheet Data', 'Scale', 'as noted')
            vs.ResetObject(titleblock)

    # Iterate through all sheet layers in the current document
    for layer in list_sheet_layer_names():

        # Define criteria strings to find title blocks and viewports on the current layer
        titleblock_crit_str = f"(((L='{layer}') & (PON='Title Block Border')))"
        viewports_crit = f"(((L='{layer}') & (T=VIEWPORT)))"

        # Use the get_objects_from_criteria() function to get lists of title blocks and viewports on the current layer
        titleblocksss = get_objects_from_criteria(titleblock_crit_str)
        imtitleblocks = imclude_titleblock(titleblocksss)
        viewports = get_objects_from_criteria(viewports_crit)

        # If there is at least one title block and one viewport on the current layer, find the largest viewport and set the scale of the title block to match
        if all([len(imtitleblocks) > 0]):
            titleblock = imtitleblocks[0]  # get single first found only
            vs.SetRField(titleblock, 'Title Block Sheet Data', 'Scale', 'n/a')
            vs.ResetObject(titleblock)
     

  2. And this, if there is a list of names:

     

    def exclude_titleblock(tblocks):
        excluded_blocks = []
        exclude_names = ['Landscape Details', 'Landscape Sections', 'Landscape Cut Sheets']
        for tblock in tblocks:
            record_name = 'Title Block Sheet Data'  # Adjust the record name based on your specific title block record
            field_name = 'Sheet Title'  # Adjust the field name based on your specific title field
            strRecordName = vs.GetRField(tblock, record_name, field_name)
            is_excluded = any(name in strRecordName for name in exclude_names)
            if not is_excluded:
                excluded_blocks.append(tblock)
        return excluded_blocks

     

  3. Ah I was able to revise it by adding this:

     

    def exclude_titleblock(tblocks):
        excluded_blocks = []
        for tblock in tblocks:
            strRecordName = vs.GetRField(tblock, 'Title Block Sheet Data', 'Sheet Title')
            if strRecordName != 'Landscape Details':
                excluded_blocks.append(tblock)
        return excluded_blocks

                             
    # Iterate through all sheet layers in the current document
    for layer in list_sheet_layer_names():

        # Define criteria strings to find title blocks and viewports on the current layer
        titleblock_crit_str = f"(((L='{layer}') & (PON='Title Block Border')))"
        viewports_crit = f"(((L='{layer}') & (T=VIEWPORT)))"

        # Use the get_objects_from_criteria() function to get lists of title blocks and viewports on the current layer
        titleblocksss = get_objects_from_criteria(titleblock_crit_str)
        titleblocks = exclude_titleblock(titleblocksss)
        viewports = get_objects_from_criteria(viewports_crit)

     

    Thanks a lot again for everyone's help!

  4. 3 hours ago, twk said:

    Apologies looks like there was an extra line after the 'while' call. correct below:

     

    # Define a function to list the names of all sheet layers in the current document
    def list_sheet_layer_names(excluded_layer_names=None):
        """
        @type filter_layer_names: exclusive layer names list ie, only these layers to be returned
        """
        layer_names = []
        hLayer = vs.FLayer()
    
        # Use a while loop and the NextLayer() function to iterate through all the sheet layers in the document
        while hLayer != None:
            if vs.GetObjectVariableInt(hLayer, 154) == 2:
                layer_name = vs.GetLName(hLayer)
                if excluded_layer_names:
                    if layer_name not in excluded_layer_names:
                        layer_names.append(layer_name)
                else:
                    layer_names.append(layer_name)
            hLayer = vs.NextLayer(hLayer)
    
        return layer_names

     

    Thanks a lot!! I realized what my problem is. I used vs.AlrtDialog(layer) at the end of this section to see what it returns and I realized it actually returns the sheet numbers rather than sheet titles. 

    Since we have all the sheet titles fixed in our template file (sheet numbers will definitely change), I am trying to find a way to use the sheet titles in the code rather than the sheet numbers. Was trying to change the index numbers in the code to get the sheet titles but had no luck..

  5. 4 hours ago, twk said:

    You know what, I misunderstood your question.

    You're wanting an excluded list.

    We'll revise the 'list_sheet_layer_names' function that accepts a list of sheets to be 'excluded' as a parameter.

     

    # Define a function to list the names of all sheet layers in the current document
    def list_sheet_layer_names(excluded_layer_names=None):
        """
        @type filter_layer_names: exclusive layer names list ie, only these layers to be returned
        """
        layer_names = []
        hLayer = vs.FLayer()
    
        # Use a while loop and the NextLayer() function to iterate through all the sheet layers in the document
        while hLayer != None:
            layer_names.append(hLayer)
            if vs.GetObjectVariableInt(hLayer, 154) == 2:
                layer_name = vs.GetLName(hLayer)
                if excluded_layer_names:
                    if layer_name not in excluded_layer_names:
                        layer_names.append(layer_name)
                else:
                    layer_names.append(layer_name)
            hLayer = vs.NextLayer(hLayer)
    
        return layer_names

     

    then when you run the iteration, you provide the list of sheet names you want excluded:

     

    # Iterate through all sheet layers in the current document
    # Say you want to exclude sheets 01, 05, 10, 12
    for layer in list_sheet_layer_names(['01', '05', '10', '12']):
    
        # Define criteria strings to find title blocks and viewports on the current layer
        titleblock_crit_str = f"(((L='{layer}') & (PON='Title Block Border')))"
        viewports_crit = f"(((L='{layer}') & (T=VIEWPORT)))"
    
        # Use the get_objects_from_criteria() function to get lists of title blocks and viewports on the current layer
        titleblocks = get_objects_from_criteria(titleblock_crit_str)
        viewports = get_objects_from_criteria(viewports_crit)
    <<< RESET OF CODE >>

     

     

     

    Thanks a lot! I tried this, I included those sheetlayer names to be excluded, but still did not work. Very strange!!

  6. 19 hours ago, twk said:

    there was a mistake in the indent blocking for the last line of the loop, the hLayer = vs.NextLayer(hLayer) shouldn't be nested in the else portion. Fixed below:
     

    # Define a function to list the names of all sheet layers in the current document
    def list_sheet_layer_names(filter_layer_names=None):
        """
        @type filter_layer_names: exclusive layer names list ie, only these layers to be returned
        """
        layer_names = []
        hLayer = vs.FLayer()
    
        # Use a while loop and the NextLayer() function to iterate through all the sheet layers in the document
        while hLayer != None:
            layer_names.append(hLayer)
            if vs.GetObjectVariableInt(hLayer, 154) == 2:
                layer_name = vs.GetLName(hLayer)
                if filter_layer_names:
                    if layer_name in filter_layer_names:
                        layer_names.append(layer_name)
                else:
                    layer_names.append(layer_name)
            hLayer = vs.NextLayer(hLayer)
    
        return layer_names

     

    Again, thanks a lot for updating this, but I still can not figure out where I should put the specific sheetlayer names that I want to exclude on this code. 

  7. 25 minutes ago, twk said:

    revised list_sheet_layer_names below, added option to provide a list of layernames you want to only be returned.

     

    # Define a function to list the names of all sheet layers in the current document
    def list_sheet_layer_names(filter_layer_names=None):
        """
        @type filter_layer_names: exclusive layer names list ie, only these layers to be returned
        """
        layer_names = []
        hLayer = vs.FLayer()
    
        # Use a while loop and the NextLayer() function to iterate through all the sheet layers in the document
        while hLayer != None:
            layer_names.append(hLayer)
            if vs.GetObjectVariableInt(hLayer, 154) == 2:
                layer_name = vs.GetLName(hLayer)
                if filter_layer_names:
                    if layer_name in filter_layer_names:
                        layer_names.append(layer_name)
                else:
                    layer_names.append(layer_name)
                    hLayer = vs.NextLayer(hLayer)
    
        return layer_names

     

    Thanks a lot! Really appreciate al your help on this!

  8. 5 minutes ago, Pat Stanford said:
      # Use a while loop and the NextLayer() function to iterate through all the sheet layers in the document
        while hLayer != None:
            layer_names.append(hLayer)
            hLayer = vs.NextLayer(hLayer)

     

    If there is just a single layer then check the layer name and don't do the append if it is that layer.

    If it is multiple layers, make a list of those layer names and compare the layer name to the list and don't do the append if they are on the exclude list.

    If there is some other criteria that you want to exclude them for, then check that criteria and don't do the append if they match that criteria.

     

    Maybe something (completely untested and my Python is very weak) like :

      # Use a while loop and the NextLayer() function to iterate through all the sheet layers in the document
        while hLayer != None:
    		if vs.GetLName != "Your Layer Name to Exclude":
                layer_names.append(hLayer)
            hLayer = vs.NextLayer(hLayer)

     

    Thanks a lot, Pat! Will test this to see! Much appreciated.

  9. On 4/13/2020 at 12:31 PM, Dylan Shaleen said:

    Hello all, 

     
    I am trying to change how the viewport scale appears on my title block for the sheet. Currently when I update the viewport's scale in sheet data, it shows a scale such as (1:48). I would like it instead to automatically update with (1/4"=1'0"). Is there anyway to change this to where it will update with the viewport scale instead of having to unlink it and manually changing it?

     

    Thanks in advance!

     

    Screen Shot 2020-04-13 at 2.30.29 PM.png

    Screen Shot 2020-04-13 at 2.30.34 PM.png

    The script I posted looks for the largest viewport on the sheet layer and updates the titleblock with its scale. 

  10. On 4/13/2020 at 12:31 PM, Dylan Shaleen said:

    Hello all, 

     
    I am trying to change how the viewport scale appears on my title block for the sheet. Currently when I update the viewport's scale in sheet data, it shows a scale such as (1:48). I would like it instead to automatically update with (1/4"=1'0"). Is there anyway to change this to where it will update with the viewport scale instead of having to unlink it and manually changing it?

     

    Thanks in advance!

     

    Screen Shot 2020-04-13 at 2.30.29 PM.png

    Screen Shot 2020-04-13 at 2.30.34 PM.png

    Hi there. There's a Python scrip developed for this with the great help of folks on the forum and I am going to post it in here. 

     

    import vs

    # Define a function to list the names of all sheet layers in the current document
    def list_sheet_layer_names():
        layer_names = []
        hLayer = vs.FLayer()

        # Use a while loop and the NextLayer() function to iterate through all the sheet layers in the document
        while hLayer != None:
            layer_names.append(hLayer)
            hLayer = vs.NextLayer(hLayer)

        # Use a lambda function to filter the list of layer names to only include sheet layers
        layer_type = lambda x:vs.GetObjectVariableInt(x, 154)
        layer_names = [vs.GetLName(x) for x in layer_names if layer_type(x) == 2]

        return layer_names

    # Define a function to get the handles of all objects in the current document that meet certain criteria
    def get_objects_from_criteria(criteria):
        object_handles = []
        def get_obj(h):
            object_handles.append(h)

        # Use the ForEachObject() function to iterate through all objects in the document and add their handles to the list if they meet the criteria
        vs.ForEachObject(get_obj, criteria)

        return object_handles

    # Define a function to calculate the area of a given object
    def get_object_area(object):
        top_left, bot_right = vs.GetBBox(object)
        length = bot_right[0] - top_left[0]
        height = top_left[1] - bot_right[1]
        return length * height

    def ImpScale(SF):

            if SF == 12:    return "1\"=1'0\""
            elif SF == 24:    return "1/2\"=1'0\""
            elif SF == 32:    return "3/8\"=1'0\""
            elif SF == 48:    return "1/4\"=1'0\""
            elif SF == 64:    return "3/16\"=1'0\""
            elif SF == 96:    return "1/8\"=1'0\""
            elif SF == 128: return "3/32\"=1'0\""
            elif SF == 192:    return "1/16\"=1'0\""
            elif SF == 384:    return "1/32\"=1'0\""
            else: return f'1:{SF:.0f}'
            
    # Iterate through all sheet layers in the current document
    for layer in list_sheet_layer_names():

        # Define criteria strings to find title blocks and viewports on the current layer
        titleblock_crit_str = f"(((L='{layer}') & (PON='Title Block Border')))"
        viewports_crit = f"(((L='{layer}') & (T=VIEWPORT)))"

        # Use the get_objects_from_criteria() function to get lists of title blocks and viewports on the current layer
        titleblocks = get_objects_from_criteria(titleblock_crit_str)
        viewports = get_objects_from_criteria(viewports_crit)

        # If there is at least one title block and one viewport on the current layer, find the largest viewport and set the scale of the title block to match
        if all([len(titleblocks)>0, len(viewports)>0]):
            titleblock = titleblocks[0] # get single first found only

            vp_area_max = 0.0
            vp_largest = None

            # Iterate through all viewports on the current layer and find the one with the largest area
            for viewport in viewports:
                vp_area = get_object_area(viewport)
                if vp_area > vp_area_max:
                    vp_area_max = vp_area
                    vp_largest = viewport
             
             # If a largest viewport is found, set the scale of the title block to match
            if vp_largest:
                SF = vs.GetObjectVariableReal(vp_largest, 1003)
                vs.SetRField(titleblock, 'Title Block Sheet Data', 'Scale', ImpScale(SF))
                vs.ResetObject(titleblock)
     

    Hope it's not too late! 🙂

  11. I revised the code to account for the imperial scales as below:

     

    import vs

     

    # Define a function to list the names of all sheet layers in the current document
    def list_sheet_layer_names():
        layer_names = []
        hLayer = vs.FLayer()

        # Use a while loop and the NextLayer() function to iterate through all the sheet layers in the document
        while hLayer != None:
            layer_names.append(hLayer)
            hLayer = vs.NextLayer(hLayer)

        # Use a lambda function to filter the list of layer names to only include sheet layers
        layer_type = lambda x:vs.GetObjectVariableInt(x, 154)
        layer_names = [vs.GetLName(x) for x in layer_names if layer_type(x) == 2]

        return layer_names

    # Define a function to get the handles of all objects in the current document that meet certain criteria
    def get_objects_from_criteria(criteria):
        object_handles = []
        def get_obj(h):
            object_handles.append(h)

        # Use the ForEachObject() function to iterate through all objects in the document and add their handles to the list if they meet the criteria
        vs.ForEachObject(get_obj, criteria)

        return object_handles

    # Define a function to calculate the area of a given object
    def get_object_area(object):
        top_left, bot_right = vs.GetBBox(object)
        length = bot_right[0] - top_left[0]
        height = top_left[1] - bot_right[1]
        return length * height

    def ImpScale(SF):

            if SF == 48:    return "1/4\"=1'0\""
            elif SF == 64:    return "3/16\"=1'0\""
            elif SF == 96:    return "1/8\"=1'0\""
            elif SF == 128: return "3/32\"=1'0\""
            elif SF == 192:    return "1/16\"=1'0\""
            elif SF == 384:    return "1/32\"=1'0\""
            else: return f'1:{SF:.0f}'
            
    # Iterate through all sheet layers in the current document
    for layer in list_sheet_layer_names():

        # Define criteria strings to find title blocks and viewports on the current layer
        titleblock_crit_str = f"(((L='{layer}') & (PON='Title Block Border')))"
        viewports_crit = f"(((L='{layer}') & (T=VIEWPORT)))"

        # Use the get_objects_from_criteria() function to get lists of title blocks and viewports on the current layer
        titleblocks = get_objects_from_criteria(titleblock_crit_str)
        viewports = get_objects_from_criteria(viewports_crit)

        # If there is at least one title block and one viewport on the current layer, find the largest viewport and set the scale of the title block to match
        if all([len(titleblocks)>0, len(viewports)>0]):
            titleblock = titleblocks[0] # get single first found only

            vp_area_max = 0.0
            vp_largest = None

            # Iterate through all viewports on the current layer and find the one with the largest area
            for viewport in viewports:
                vp_area = get_object_area(viewport)
                if vp_area > vp_area_max:
                    vp_area_max = vp_area
                    vp_largest = viewport
             
             # If a largest viewport is found, set the scale of the title block to match
            if vp_largest:
                SF = vs.GetObjectVariableReal(vp_largest, 1003)
                vs.SetRField(titleblock, 'Title Block Sheet Data', 'Scale', ImpScale(SF))
                vs.ResetObject(titleblock)


    Again, thanks a lot all for helping me on this! 

    • Like 2
  12. On 4/28/2023 at 8:27 AM, twk said:

    And here is what I came up with, (FYI, I used chatGPT to explain the code with inline comments!).
    ** As always, save before running the script, and no responsibility taken for loss of work 😅 **

     

    import vs
    
    # Define a function to list the names of all sheet layers in the current document
    def list_sheet_layer_names():
        layer_names = []
        hLayer = vs.FLayer()
    
        # Use a while loop and the NextLayer() function to iterate through all the sheet layers in the document
        while hLayer != None:
            layer_names.append(hLayer)
            hLayer = vs.NextLayer(hLayer)
    
        # Use a lambda function to filter the list of layer names to only include sheet layers
        layer_type = lambda x:vs.GetObjectVariableInt(x, 154)
        layer_names = [vs.GetLName(x) for x in layer_names if layer_type(x) == 2]
    
        return layer_names
    
    # Define a function to get the handles of all objects in the current document that meet certain criteria
    def get_objects_from_criteria(criteria):
        object_handles = []
        def get_obj(h):
            object_handles.append(h)
    
        # Use the ForEachObject() function to iterate through all objects in the document and add their handles to the list if they meet the criteria
        vs.ForEachObject(get_obj, criteria)
    
        return object_handles
    
    # Define a function to calculate the area of a given object
    def get_object_area(object):
        top_left, bot_right = vs.GetBBox(object)
        length = bot_right[0] - top_left[0]
        height = top_left[1] - bot_right[1]
        return length * height
    
    # Iterate through all sheet layers in the current document
    for layer in list_sheet_layer_names():
    
        # Define criteria strings to find title blocks and viewports on the current layer
        titleblock_crit_str = f"(((L='{layer}') & (PON='Title Block Border')))"
        viewports_crit = f"(((L='{layer}') & (T=VIEWPORT)))"
    
        # Use the get_objects_from_criteria() function to get lists of title blocks and viewports on the current layer
        titleblocks = get_objects_from_criteria(titleblock_crit_str)
        viewports = get_objects_from_criteria(viewports_crit)
    
        # If there is at least one title block and one viewport on the current layer, find the largest viewport and set the scale of the title block to match
        if all([len(titleblocks)>0, len(viewports)>0]):
            titleblock = titleblocks[0] # get single first found only
    
            vp_area_max = 0.0
            vp_largest = None
    
            # Iterate through all viewports on the current layer and find the one with the largest area
            for viewport in viewports:
                vp_area = get_object_area(viewport)
                if vp_area > vp_area_max:
                    vp_area_max = vp_area
                    vp_largest = viewport
    
            # If a largest viewport is found, set the scale of the title block to match
            if vp_largest:
                vp_scale = vs.GetObjectVariableReal(vp_largest, 1003)
                vs.SetRField(titleblock, 'Title Block Sheet Data', 'Scale', f'1:{vp_scale:.0f}')

     

     

    11 hours ago, MullinRJ said:

    If a function doesn't exist, you can always create a lookup function for the typical values you find in Imperial Scales.

     

    Something like this:

    def ImpScale(SF):	# return the imperial scale string for typical Layer Scale Factor values (SF)
    	if SF == 4:	return '3"'
    	elif SF == 6:	return '2"'
    	elif SF == 8:	return '1-1/2"'
    	elif SF == 12:	return '1"'
    	elif SF == 16:	return '3/4"'
    	elif SF == 24:	return '1/2"'
    	elif SF == 32:	return '3/8"'
    
    	elif SF == 48:	return '1/4"'
    	elif SF == 64:	return '3/16"'
    	elif SF == 96:	return '1/8"'
    	elif SF == 192:	return '1/16"'
    	elif SF == 384:	return '1/32"'
    
    	elif SF == 120:	return '1"='+"10'"
    	elif SF == 240:	return '1"='+"20'"
    	elif SF == 360:	return '1"='+"30'"
    	elif SF == 480:	return '1"='+"40'"
    	elif SF == 600:	return '1"='+"50'"
    	elif SF == 1200: return '1"='+"100'"
    	else: return '1:'+str(SF)
    
    
    SF = 1
    while not vs.DidCancel():
    	SF = vs.IntDialog( 'Enter a scale factor', str(SF))
    	if not vs.DidCancel():
    		vs.AlrtDialog(ImpScale(SF))	# test the function

     

    Raymond

    This is very helpful! Thank you so much!

     

  13. 11 minutes ago, Pat Stanford said:

    You should be able to add

     

    vs.ResetObject(titleblock)

     

    at the end (or if you are processing multiple title blocks, at the end of the block doing the processing) and have each one reset individually instead of resetting everything in the drawing.

    Hi Pat, I just added that in and it works like a magic! Thanks a lot! Now I am trying to add some "if" loops for converting the engineering scales to Architectural...I will keep you posted on how it goes!

    • Like 1
  14. 13 minutes ago, Neda Roohnia said:

    Hi there, thanks a lot for sending the two versions of your script! I just realized that they both work actually, the only thing is that I have to "update" the titleblock for the scale to update by checking and un-checking "Activate Title Block" on the object info panel. I was wondering if there is a way to include this "updating" into the script somehow. My other question is that how should I change the script to show the imperial scales properly.. i.e. 1/8" = 1'0" instead of 1:96. Many thanks! 

     

    On 4/28/2023 at 8:27 AM, twk said:

    And here is what I came up with, (FYI, I used chatGPT to explain the code with inline comments!).
    ** As always, save before running the script, and no responsibility taken for loss of work 😅 **

     

    import vs
    
    # Define a function to list the names of all sheet layers in the current document
    def list_sheet_layer_names():
        layer_names = []
        hLayer = vs.FLayer()
    
        # Use a while loop and the NextLayer() function to iterate through all the sheet layers in the document
        while hLayer != None:
            layer_names.append(hLayer)
            hLayer = vs.NextLayer(hLayer)
    
        # Use a lambda function to filter the list of layer names to only include sheet layers
        layer_type = lambda x:vs.GetObjectVariableInt(x, 154)
        layer_names = [vs.GetLName(x) for x in layer_names if layer_type(x) == 2]
    
        return layer_names
    
    # Define a function to get the handles of all objects in the current document that meet certain criteria
    def get_objects_from_criteria(criteria):
        object_handles = []
        def get_obj(h):
            object_handles.append(h)
    
        # Use the ForEachObject() function to iterate through all objects in the document and add their handles to the list if they meet the criteria
        vs.ForEachObject(get_obj, criteria)
    
        return object_handles
    
    # Define a function to calculate the area of a given object
    def get_object_area(object):
        top_left, bot_right = vs.GetBBox(object)
        length = bot_right[0] - top_left[0]
        height = top_left[1] - bot_right[1]
        return length * height
    
    # Iterate through all sheet layers in the current document
    for layer in list_sheet_layer_names():
    
        # Define criteria strings to find title blocks and viewports on the current layer
        titleblock_crit_str = f"(((L='{layer}') & (PON='Title Block Border')))"
        viewports_crit = f"(((L='{layer}') & (T=VIEWPORT)))"
    
        # Use the get_objects_from_criteria() function to get lists of title blocks and viewports on the current layer
        titleblocks = get_objects_from_criteria(titleblock_crit_str)
        viewports = get_objects_from_criteria(viewports_crit)
    
        # If there is at least one title block and one viewport on the current layer, find the largest viewport and set the scale of the title block to match
        if all([len(titleblocks)>0, len(viewports)>0]):
            titleblock = titleblocks[0] # get single first found only
    
            vp_area_max = 0.0
            vp_largest = None
    
            # Iterate through all viewports on the current layer and find the one with the largest area
            for viewport in viewports:
                vp_area = get_object_area(viewport)
                if vp_area > vp_area_max:
                    vp_area_max = vp_area
                    vp_largest = viewport
    
            # If a largest viewport is found, set the scale of the title block to match
            if vp_largest:
                vp_scale = vs.GetObjectVariableReal(vp_largest, 1003)
                vs.SetRField(titleblock, 'Title Block Sheet Data', 'Scale', f'1:{vp_scale:.0f}')

     

    Oh I figured a partial answer to one of my questions; I need to go to Tools...> Utilities...> Reset All Plug-ins and then it works!

  15. On 4/28/2023 at 8:27 AM, twk said:

    And here is what I came up with, (FYI, I used chatGPT to explain the code with inline comments!).
    ** As always, save before running the script, and no responsibility taken for loss of work 😅 **

     

    import vs
    
    # Define a function to list the names of all sheet layers in the current document
    def list_sheet_layer_names():
        layer_names = []
        hLayer = vs.FLayer()
    
        # Use a while loop and the NextLayer() function to iterate through all the sheet layers in the document
        while hLayer != None:
            layer_names.append(hLayer)
            hLayer = vs.NextLayer(hLayer)
    
        # Use a lambda function to filter the list of layer names to only include sheet layers
        layer_type = lambda x:vs.GetObjectVariableInt(x, 154)
        layer_names = [vs.GetLName(x) for x in layer_names if layer_type(x) == 2]
    
        return layer_names
    
    # Define a function to get the handles of all objects in the current document that meet certain criteria
    def get_objects_from_criteria(criteria):
        object_handles = []
        def get_obj(h):
            object_handles.append(h)
    
        # Use the ForEachObject() function to iterate through all objects in the document and add their handles to the list if they meet the criteria
        vs.ForEachObject(get_obj, criteria)
    
        return object_handles
    
    # Define a function to calculate the area of a given object
    def get_object_area(object):
        top_left, bot_right = vs.GetBBox(object)
        length = bot_right[0] - top_left[0]
        height = top_left[1] - bot_right[1]
        return length * height
    
    # Iterate through all sheet layers in the current document
    for layer in list_sheet_layer_names():
    
        # Define criteria strings to find title blocks and viewports on the current layer
        titleblock_crit_str = f"(((L='{layer}') & (PON='Title Block Border')))"
        viewports_crit = f"(((L='{layer}') & (T=VIEWPORT)))"
    
        # Use the get_objects_from_criteria() function to get lists of title blocks and viewports on the current layer
        titleblocks = get_objects_from_criteria(titleblock_crit_str)
        viewports = get_objects_from_criteria(viewports_crit)
    
        # If there is at least one title block and one viewport on the current layer, find the largest viewport and set the scale of the title block to match
        if all([len(titleblocks)>0, len(viewports)>0]):
            titleblock = titleblocks[0] # get single first found only
    
            vp_area_max = 0.0
            vp_largest = None
    
            # Iterate through all viewports on the current layer and find the one with the largest area
            for viewport in viewports:
                vp_area = get_object_area(viewport)
                if vp_area > vp_area_max:
                    vp_area_max = vp_area
                    vp_largest = viewport
    
            # If a largest viewport is found, set the scale of the title block to match
            if vp_largest:
                vp_scale = vs.GetObjectVariableReal(vp_largest, 1003)
                vs.SetRField(titleblock, 'Title Block Sheet Data', 'Scale', f'1:{vp_scale:.0f}')

     

    Hi there, thanks a lot for sending the two versions of your script! I just realized that they both work actually, the only thing is that I have to "update" the titleblock for the scale to update by checking and un-checking "Activate Title Block" on the object info panel. I was wondering if there is a way to include this "updating" into the script somehow. My other question is that how should I change the script to show the imperial scales properly.. i.e. 1/8" = 1'0" instead of 1:96. Many thanks! 

  16. On 4/28/2023 at 8:27 AM, twk said:

    And here is what I came up with, (FYI, I used chatGPT to explain the code with inline comments!).
    ** As always, save before running the script, and no responsibility taken for loss of work 😅 **

     

    import vs
    
    # Define a function to list the names of all sheet layers in the current document
    def list_sheet_layer_names():
        layer_names = []
        hLayer = vs.FLayer()
    
        # Use a while loop and the NextLayer() function to iterate through all the sheet layers in the document
        while hLayer != None:
            layer_names.append(hLayer)
            hLayer = vs.NextLayer(hLayer)
    
        # Use a lambda function to filter the list of layer names to only include sheet layers
        layer_type = lambda x:vs.GetObjectVariableInt(x, 154)
        layer_names = [vs.GetLName(x) for x in layer_names if layer_type(x) == 2]
    
        return layer_names
    
    # Define a function to get the handles of all objects in the current document that meet certain criteria
    def get_objects_from_criteria(criteria):
        object_handles = []
        def get_obj(h):
            object_handles.append(h)
    
        # Use the ForEachObject() function to iterate through all objects in the document and add their handles to the list if they meet the criteria
        vs.ForEachObject(get_obj, criteria)
    
        return object_handles
    
    # Define a function to calculate the area of a given object
    def get_object_area(object):
        top_left, bot_right = vs.GetBBox(object)
        length = bot_right[0] - top_left[0]
        height = top_left[1] - bot_right[1]
        return length * height
    
    # Iterate through all sheet layers in the current document
    for layer in list_sheet_layer_names():
    
        # Define criteria strings to find title blocks and viewports on the current layer
        titleblock_crit_str = f"(((L='{layer}') & (PON='Title Block Border')))"
        viewports_crit = f"(((L='{layer}') & (T=VIEWPORT)))"
    
        # Use the get_objects_from_criteria() function to get lists of title blocks and viewports on the current layer
        titleblocks = get_objects_from_criteria(titleblock_crit_str)
        viewports = get_objects_from_criteria(viewports_crit)
    
        # If there is at least one title block and one viewport on the current layer, find the largest viewport and set the scale of the title block to match
        if all([len(titleblocks)>0, len(viewports)>0]):
            titleblock = titleblocks[0] # get single first found only
    
            vp_area_max = 0.0
            vp_largest = None
    
            # Iterate through all viewports on the current layer and find the one with the largest area
            for viewport in viewports:
                vp_area = get_object_area(viewport)
                if vp_area > vp_area_max:
                    vp_area_max = vp_area
                    vp_largest = viewport
    
            # If a largest viewport is found, set the scale of the title block to match
            if vp_largest:
                vp_scale = vs.GetObjectVariableReal(vp_largest, 1003)
                vs.SetRField(titleblock, 'Title Block Sheet Data', 'Scale', f'1:{vp_scale:.0f}')

     

    It's very strange! I tried the code, it doesn't give any errors, but it doesn't do anything, either! I was thinking of a couple of things; what if I revise it in a way that it mentions the titleblock's name directly rather than search for the titleblocks? The titleblock symbol's name is defined in our template file. I appreciate if you point out to any possible issue that causes this! Again, really appreciate your input and help!!

  17. 14 minutes ago, twk said:

    And here is what I came up with, (FYI, I used chatGPT to explain the code with inline comments!).
    ** As always, save before running the script, and no responsibility taken for loss of work 😅 **
    Thanks soo much, I really appreciate your very quick response and help!

    I will let you know in case of any issues! Ah yea, ChatGPT is awesome for that, it confused me tho to generate this code!! 😄


     

    import vs
    
    # Define a function to list the names of all sheet layers in the current document
    def list_sheet_layer_names():
        layer_names = []
        hLayer = vs.FLayer()
    
        # Use a while loop and the NextLayer() function to iterate through all the sheet layers in the document
        while hLayer != None:
            layer_names.append(hLayer)
            hLayer = vs.NextLayer(hLayer)
    
        # Use a lambda function to filter the list of layer names to only include sheet layers
        layer_type = lambda x:vs.GetObjectVariableInt(x, 154)
        layer_names = [vs.GetLName(x) for x in layer_names if layer_type(x) == 2]
    
        return layer_names
    
    # Define a function to get the handles of all objects in the current document that meet certain criteria
    def get_objects_from_criteria(criteria):
        object_handles = []
        def get_obj(h):
            object_handles.append(h)
    
        # Use the ForEachObject() function to iterate through all objects in the document and add their handles to the list if they meet the criteria
        vs.ForEachObject(get_obj, criteria)
    
        return object_handles
    
    # Define a function to calculate the area of a given object
    def get_object_area(object):
        top_left, bot_right = vs.GetBBox(object)
        length = bot_right[0] - top_left[0]
        height = top_left[1] - bot_right[1]
        return length * height
    
    # Iterate through all sheet layers in the current document
    for layer in list_sheet_layer_names():
    
        # Define criteria strings to find title blocks and viewports on the current layer
        titleblock_crit_str = f"(((L='{layer}') & (PON='Title Block Border')))"
        viewports_crit = f"(((L='{layer}') & (T=VIEWPORT)))"
    
        # Use the get_objects_from_criteria() function to get lists of title blocks and viewports on the current layer
        titleblocks = get_objects_from_criteria(titleblock_crit_str)
        viewports = get_objects_from_criteria(viewports_crit)
    
        # If there is at least one title block and one viewport on the current layer, find the largest viewport and set the scale of the title block to match
        if all([len(titleblocks)>0, len(viewports)>0]):
            titleblock = titleblocks[0] # get single first found only
    
            vp_area_max = 0.0
            vp_largest = None
    
            # Iterate through all viewports on the current layer and find the one with the largest area
            for viewport in viewports:
                vp_area = get_object_area(viewport)
                if vp_area > vp_area_max:
                    vp_area_max = vp_area
                    vp_largest = viewport
    
            # If a largest viewport is found, set the scale of the title block to match
            if vp_largest:
                vp_scale = vs.GetObjectVariableReal(vp_largest, 1003)
                vs.SetRField(titleblock, 'Title Block Sheet Data', 'Scale', f'1:{vp_scale:.0f}')

     

     

  18. Hi everyone,

     

    I am trying to come up with a Python script that identifies the largest viewport on a sheetlayer, gets its scale, and updates the title block scale field for each sheetlayer. 

    I have put together a very preliminary code for this.

     

    import vs

     

    Handle = vs.GetObject('THISISIT')
    strNR1 = vs.GetObjectVariableReal(Handle, 1003)

    #Sheet data record format and field
    strRecordName = 'Title Block Sheet Data'
    strRecordField = 'Scale'

    def SetRecord(h):
        vs.SetRField(h,strRecordName,strRecordField,strNR1);
        vs.ResetObject(h);
        
    criteria = '((R in [' + "'" + strRecordName + "'" + ']))';

    vs.ForEachObject( SetRecord, criteria);

     

    This code works as long as I know the viewport's name (in this example:  "THISISIT"), also it puts the same scale on all the sheetlayers' titleblocks. 

    Any inputs will be much appreciated! 

     

  19. On 4/13/2022 at 1:17 PM, Pat Stanford said:

    If you are using the Title Block Border object I don't think you can use this at all. 

     

    You might be able to use a worksheet script to store the value into a Record.Field attached to your title block and then possibly use that as a text field.

     

    I don't think I fully understand what you want to be able to do.

    Thanks a lot, Pat. I am exactly trying to do what you mentioned in here. Trying to use the worksheet to store the value into a Record.Field attached to my title block and use it there. I just don't know how to do it!

  20. On 4/13/2022 at 8:05 PM, Mark Aceto said:

     

    It's a logic problem. I have a friend that has been asking for this for years, and my response has always been the same, "How would VW manage that with more than 1 viewport on the same sheet layer but not all of the viewports are the same scale?"

    Agreed! But what if it asks for some more criteria like class etc.? Then it can filter the main one and get the scale. 

    • Like 1
  21. 17 hours ago, Mark Aceto said:

     

    It's a logic problem. I have a friend that has been asking for this for years, and my response has always been the same, "How would VW manage that with more than 1 viewport on the same sheet layer but not all of the viewports are the same scale?"

    That's a very good point! They can set it up in a way that if there is more than one VP on the sheet layer the titleblock text show: N/A or something like that.

  22. On 8/2/2020 at 10:04 PM, Boh said:

    How bizzare! Yes I added a couple of columns and now it works. I then deleted both the columns and it still works. Bugsville!

     

    How bizzare also that you managed to figure that out!!!!

     

     

    On 1/9/2018 at 9:55 AM, Pat Stanford said:

    OK, here you go.

     

    There are two scripts attached. One that returns the scale as a real number, the other that returns it as a string showing as "1:Scale".

     

    If you save these scripts into your file (any script palette will do), then you can call them in a worksheet by using a function of "=RunScript('ScriptName')". Where the script name is replaced by the name you are showing in the script palette. Copy everything in the code blocks below. You can name the scripts anything you want, but I named them "Get_VP_Scale" and "Get_VP_Scale_Text".

     

    If you want to be able to use these across multiple files without having to have the script in each file, create a new VW file that contains the script(s) and save it in the Defaults folder for Reports and Schedules.  /Users/Your User Name/Library/Application Support/VectorWorks/2017/Libraries/Defaults/Reports_Schedules.  

     

    Then modify the function in the worksheet to "=RunScript(120,'ScriptName')

     

    If you need a different format, the scripts can be embellished as necessary to do other processing of the numbers/text to get the output you want.

     

    Procedure Get_VP_Scale;
    
    Var	H1:Handle;
    	R1:Real;
    	
    	
    Begin
    	H1:=WSScript_GetObject;
    	R1:=GetObjectVariableReal(H1,1003);
    	WSScript_SetResReal(R1);  
    
    End;
    
    Run(Get_VP_Scale);

     

    Procedure Get_VP_Scale_Text;
    
    Var	H1,H2:Handle;
    	N1:Integer;
    	R1:Real;
    	S1:String;
    	
    	
    Begin
    	H1:=WSScript_GetObject;
    	R1:=GetObjectVariableReal(H1,1003);
    	WSScript_SetResStr(Concat('1:',R1));  
    
    End;
    
    Run(Get_VP_Scale_Text);

     

     

    On 8/2/2020 at 9:26 PM, Pat Stanford said:

    The scripts were written in 2018, so they should work in 2019. Don't know what else to tell you.

     

    I just downloaded VW2019.  You are correct. It is broken in 2019SP6.  😞

     

    BUT, there seems to be a strange work around. If you add two blank columns to the right of the column(s) with the Runscript commands, then they calculate correctly.

     

    VERY strange.

    Hi 

     

    On 1/9/2018 at 9:55 AM, Pat Stanford said:

    OK, here you go.

     

    There are two scripts attached. One that returns the scale as a real number, the other that returns it as a string showing as "1:Scale".

     

    If you save these scripts into your file (any script palette will do), then you can call them in a worksheet by using a function of "=RunScript('ScriptName')". Where the script name is replaced by the name you are showing in the script palette. Copy everything in the code blocks below. You can name the scripts anything you want, but I named them "Get_VP_Scale" and "Get_VP_Scale_Text".

     

    If you want to be able to use these across multiple files without having to have the script in each file, create a new VW file that contains the script(s) and save it in the Defaults folder for Reports and Schedules.  /Users/Your User Name/Library/Application Support/VectorWorks/2017/Libraries/Defaults/Reports_Schedules.  

     

    Then modify the function in the worksheet to "=RunScript(120,'ScriptName')

     

    If you need a different format, the scripts can be embellished as necessary to do other processing of the numbers/text to get the output you want.

     

    Procedure Get_VP_Scale;
    
    Var	H1:Handle;
    	R1:Real;
    	
    	
    Begin
    	H1:=WSScript_GetObject;
    	R1:=GetObjectVariableReal(H1,1003);
    	WSScript_SetResReal(R1);  
    
    End;
    
    Run(Get_VP_Scale);

     

    Procedure Get_VP_Scale_Text;
    
    Var	H1,H2:Handle;
    	N1:Integer;
    	R1:Real;
    	S1:String;
    	
    	
    Begin
    	H1:=WSScript_GetObject;
    	R1:=GetObjectVariableReal(H1,1003);
    	WSScript_SetResStr(Concat('1:',R1));  
    
    End;
    
    Run(Get_VP_Scale_Text);

     

    Hi Pat, this works perfectly! How can I use this directly for my titleblock to update the sheet scales automatically?

  23. 6 minutes ago, Andy Broomell said:

     

    Are you cutting and pasting, or are you selecting the Viewport and changing which Sheet it's on via the Object Info Palette?

    Hi Andy, thanks a lot for your reply! Yes, I was cutting and pasting, I just realized if I change the sheet number on the object info palette, that won't happen! Now there is another issue; if I delete the viewport, the callout on the other sheet disappears! Is there a setting to keep the callout with a broken link symbol on it or something? (to show it is not linked to anything)

    • Like 3
  24. Hi everyone. 

    I just learned about the very cool new feature in Vectorworks 2021; the more flexible detail callout that can be linked to a particular viewport and synced automatically.

    However, it seems this feature has a flaw, and that is when I move a view port to a different sheet layer, the detail callout disappears instead of getting updated based on the new sheet layer number/info. Does anyone know a solution to this?

     

    Thanks a lot!

×
×
  • Create New...