Link DWG from ACC

Anyway to link the CAD from ACC cloud file?
Same script is ok for local file, but fail in accessing the ACC cloud version.

Hi,

you must use the folder link via Desktop Connector it seems to me that there is no other solution to date (for non-cloud files)

Is there any chance that i can access via GUID or acc folder path of the dwg file in ACC via dynamo / code?

There is no API call to generate the link to an ACC path at this time, even if you have the cloud path.

2 Likes

Here is a good cheat! : )

# Import required .NET assemblies for Revit API and Dynamo interop
import clr
import os

clr.AddReference("RevitAPI")
clr.AddReference("RevitServices")
clr.AddReference("RevitNodes")

# Import necessary Revit and Dynamo namespaces
import Autodesk
from Autodesk.Revit.DB import ModelPathUtils
from RevitServices.Persistence import DocumentManager

# Get the current active Revit document
doc = DocumentManager.Instance.CurrentDBDocument

# Handle optional inputs:
# IN[0]: Custom ACC Desktop Connector base path
# IN[1]: Boolean to control whether file extensions should be shown (default False)
show_ext = IN[1] if len(IN) > 1 and isinstance(IN[1], bool) else False

# Determine the Desktop Connector base path
if len(IN) > 0 and IN[0]:
    # Use the provided custom path
    custom_dc_base = IN[0]
else:
    # Default to: C:\Users\[username]\DC\ACCDocs
    import getpass
    user = getpass.getuser()
    custom_dc_base = os.path.join("C:\\Users", user, "DC", "ACCDocs")


# Function: Remove file extension from a path or filename if show_ext is False
def strip_ext(path):
    if path and not show_ext:
        return os.path.splitext(path)[0]
    return path


# Function: Recursively search the dc_base path for a filename match (case-insensitive)
def find_file_by_name(filename, search_root):
    for root, _, files in os.walk(search_root):
        for f in files:
            if f.lower() == filename.lower():
                return os.path.join(root, f)
    return None


# Function: Resolve the ACC path to a Desktop Connector local file path
def resolve_acc_local_path(acc_url_path, dc_base):
    """
    First try to construct the direct Desktop Connector path.
    If not found, fallback to a recursive filename search in dc_base.
    """
    if not acc_url_path:
        return None
    try:
        # Convert ACC path format to Windows file system path
        rel_path = acc_url_path.replace("Autodesk Docs://", "").replace("/", "\\")
        candidate_path = os.path.join(dc_base, rel_path)
        if os.path.exists(candidate_path):
            return candidate_path
        else:
            # Fallback: search for the filename only under the root
            filename = os.path.basename(rel_path)
            return find_file_by_name(filename, dc_base)
    except:
        return None


# --- Raw internal path assignments (always include extensions) ---

# Get full path of current document (may be empty for new/unsaved)
doc_path = doc.PathName

# Document name (with extension, to be stripped later if needed)
doc_title = doc.Title

# Local path: used if not workshared or if it's a family document
local_path = doc_path if (doc.IsFamilyDocument or not doc.IsWorkshared) else None

# Central model path (only if workshared)
central_path = None
if doc.IsWorkshared:
    try:
        central_path = ModelPathUtils.ConvertModelPathToUserVisiblePath(doc.GetWorksharingCentralModelPath())
    except:
        pass  # Leave as None if error occurs

# ACC path (cloud-hosted path)
acc_path = None
try:
    acc_path = ModelPathUtils.ConvertModelPathToUserVisiblePath(doc.GetCloudModelPath())
except:
    pass  # Leave as None if cloud model path is not available

# Local ACC path via Desktop Connector (using resolved match or search)
acc_local_path = resolve_acc_local_path(acc_path, custom_dc_base)


# --- Build output list of 7 elements ---
# [0] = Preferred path (best available from Desktop, ACC, Central, Local)
# [1] = File name
# [2] = File extension (RVT, RFA, etc.)
# [3] = Local path (non-workshared or families)
# [4] = Central model path
# [5] = ACC cloud path
# [6] = Desktop Connector local path

output = [None] * 7

# 0. Preferred path logic: Choose best path in order of priority
for candidate in [acc_local_path, acc_path, central_path, local_path]:
    if candidate:
        output[0] = strip_ext(candidate)
        break

# 1. Filename: Use doc title, strip extension if requested
output[1] = doc_title if show_ext else os.path.splitext(doc_title)[0]

# 2. File extension: Always output, not stripped
output[2] = os.path.splitext(doc_path)[1][1:] if doc_path else None

# 3. Local path
output[3] = strip_ext(local_path)

# 4. Central path
output[4] = strip_ext(central_path)

# 5. ACC path (cloud)
output[5] = strip_ext(acc_path)

# 6. ACC path (Desktop Connector local path)
output[6] = strip_ext(acc_local_path)

# Final result returned to Dynamo
OUT = output

The acc_local_path is a ‘best educated guess’ based on the file name and project extracted from the ACC docs.

If the boolean input in in[1] is False then it strips the extension. Handy for writing out e.g. excel files same name as project/family file without the extension. (How I organize associative content)

The code block:

preferred = IN[0];
fnName = IN[1];
ext = IN[2];
loclFp = IN[3];
central = IN[4];
accHTTP = IN[5];
docsFp = IN[6];

OUT = [preferred, fnName, ext, loclFp, central, accHTTP, docsFp];

Man how I wished BlueBeam did this for figuring out output paths!

I would upload the DYF but can’t as my account got munched when I left WM.