ワークシェアリングされているドキュメントを開く

ワークシェアリングされているドキュメントを開く

Application.OpenDocumentFile(ModelPath, OpenOptions)メソッドを使用すると、ワークシェアリングされているドキュメントを開く操作に関連するオプションを設定することができます。中央ドキュメントからアタッチ解除したり、オーナ以外のユーザがローカル ファイルを読み込み専用で開くことを許可するオプション以外にも、ワークセットに関連するオプションを設定することができます。ワークシェアリングされているドキュメントを開く場合、すべてのシステム ワークセットは自動的に開きますが、ユーザ作成のワークセットについては開くまたは閉じるを指定できます。開いているワークセット内の要素を展開し、表示することができます。ただし、閉じたワークセット内の要素は展開されないようにするために表示されません。現在のセッションに必要なワークセットのみを開くことにより、Revit のメモリ使用量が低減され、パフォーマンスが改善します。

次の例では、2 つのワークセットを開くように指定して、ドキュメントを開きます。WorksharingUtils.GetUserWorksetInfo()メソッドを使用すると、閉じられた Revit ドキュメントからワークセット情報にアクセスできる点に注意してください。

コード領域: ワークシェアリングされたドキュメントを開く

Document OpenDocumentWithWorksets(Application app, ModelPath projectPath)
{
    Document doc = null;
    try
    {
        // Get info on all the user worksets in the project prior to opening
        IList<WorksetPreview> worksets = WorksharingUtils.GetUserWorksetInfo(projectPath);
        IList<WorksetId> worksetIds = new List<WorksetId>();
        // Find two predetermined worksets
        foreach (WorksetPreview worksetPrev in worksets)
        {
            if (worksetPrev.Name.CompareTo("Workset1") == 0 ||
                worksetPrev.Name.CompareTo("Workset2") == 0)
            {
                worksetIds.Add(worksetPrev.Id);
            }
        }

        OpenOptions openOptions = new OpenOptions();
        // Setup config to close all worksets by default
        WorksetConfiguration openConfig = new WorksetConfiguration(WorksetConfigurationOption.CloseAllWorksets);
        // Set list of worksets for opening 
        openConfig.Open(worksetIds);
        openOptions.SetOpenWorksetsConfiguration(openConfig);
        doc = app.OpenDocumentFile(projectPath, openOptions);
    }
    catch (Exception e)
    {
        TaskDialog.Show("Open File Failed", e.Message);
    }

    return doc;
}

ドキュメントを開いて、最後に表示したワークセットのみを開くオプションもあります。

コード領域: 最後に表示したワークセットを開く

public static Document OpenLastViewed(UIApplication uiApplication)
{
    Application application = uiApplication.Application;

    // Setup options
    OpenOptions options1 = new OpenOptions();

    // Default config opens all.  Close all first, then open last viewed to get the correct settings.
    WorksetConfiguration worksetConfig = new WorksetConfiguration(WorksetConfigurationOption.OpenLastViewed);
    options1.SetOpenWorksetsConfiguration(worksetConfig);

    // Open the document
    Document openedDoc = application.OpenDocumentFile(GetWSAPIModelPath("WorkaredFileSample.rvt"), options1);

    return openedDoc;
}

private static ModelPath GetWSAPIModelPath(string fileName)
{
    // Utility to get a local path for a target model file
    FileInfo filePath = new FileInfo(Path.Combine(@"C:\Documents\Revit Projects", fileName));
    ModelPath mp = ModelPathUtils.ConvertUserVisiblePathToModelPath(filePath.FullName);

    return mp;
}
次の 2 つの例は、まずディスクや Revit Server から新しいローカル モデルを作成し、次にそれを開く方法を示しています。下の例は、前の例で使用した GetWSAPIModelPath()メソッドを使用していることに注意してください。

コード領域: ディスクから新しいローカル モデルを開く

public static Document OpenNewLocalFromDisk(UIApplication uiApplication)
{
    // Create new local from a disk location
    ModelPath newLocalPath = GetWSAPIModelPath("LocalWorksharing.rvt");
    return (OpenNewLocalFromModelPath(uiApplication.Application, GetWSAPIModelPath("NewLocalWorksharing.rvt"), newLocalPath));
}


private static Document OpenNewLocalFromModelPath(Application app, ModelPath centralPath, ModelPath localPath)
{
    // Create the new local at the given path
    WorksharingUtils.CreateNewLocal(centralPath, localPath);

    // Select specific worksets to open
    // First get a list of worksets from the unopened document
    IList<WorksetPreview> worksets = WorksharingUtils.GetUserWorksetInfo(localPath);
    List<WorksetId> worksetsToOpen = new List<WorksetId>();

    foreach (WorksetPreview preview in worksets)
    {
        // Match worksets to open with criteria
        if (preview.Name.StartsWith("O"))
            worksetsToOpen.Add(preview.Id);
    }

    // Setup option to open the target worksets
    // First close all, then set specific ones to open
    WorksetConfiguration worksetConfig = new WorksetConfiguration(WorksetConfigurationOption.CloseAllWorksets);
    worksetConfig.Open(worksetsToOpen);

    // Open the new local
    OpenOptions options1 = new OpenOptions();
    options1.SetOpenWorksetsConfiguration(worksetConfig);
    Document openedDoc = app.OpenDocumentFile(localPath, options1);

    return openedDoc;
}
次の例は、前の例の一部として説明した OpenNewLocalFromModelPath()メソッドを使用します。

コード領域: Revit Server から新しいローカル モデルを開く

/// <summary>
/// Get the server path for a particular model and open a new local copy
/// </summary>
public static Document OpenNewLocalFromServer(UIApplication uiApp)
{
    // Create new local from a server location
    Application app = uiApp.Application;

    // Get the host id/IP of the server
    String hostId = app.GetRevitServerNetworkHosts().First();

    // try to get the server path for the particular model on the server
    String rootFolder = "|";
    ModelPath serverPath = FindWSAPIModelPathOnServer(app, hostId, rootFolder, "WorksharingOnServer.rvt");

    ModelPath newLocalPath = GetWSAPIModelPath("WorksharingLocalFromServer.rvt");
    return (OpenNewLocalFromModelPath(uiApp.Application, serverPath, newLocalPath));
}

/// <summary>
/// Uses the Revit Server REST API to recursively search the folders of the Revit Server for a particular model.
/// </summary>
private static ModelPath FindWSAPIModelPathOnServer(Application app, string hostId, string folderName, string fileName)
{
    // Connect to host to find list of available models (the "/contents" flag)
    XmlDictionaryReader reader = GetResponse(app, hostId, folderName + "/contents");
    bool found = false;

    // Look for the target model name in top level folder
    List<String> folders = new List<String>();
    while (reader.Read())
    {
        // Save a list of subfolders, if found
        if (reader.NodeType == XmlNodeType.Element && reader.Name == "Folders")
        {
            while (reader.Read())
            {
                if (reader.NodeType == XmlNodeType.EndElement && reader.Name == "Folders")
                    break;

                if (reader.NodeType == XmlNodeType.Element && reader.Name == "Name")
                {
                    reader.Read();
                    folders.Add(reader.Value);
                }
            }
        }
        // Check for a matching model at this folder level
        if (reader.NodeType == XmlNodeType.Element && reader.Name == "Models")
        {
            found = FindModelInServerResponseJson(reader, fileName);
            if (found)
                break;
        }
    }

    reader.Close();

    // Build the model path to match the found model on the server
    if (found)
    {
        // Server URLs use "|" for folder separation, Revit API uses "/"
        String folderNameFragment = folderName.Replace('|', '/');

        // Add trailing "/" if not present
        if (!folderNameFragment.EndsWith("/"))
            folderNameFragment += "/";

        // Build server path
        ModelPath modelPath = new ServerPath(hostId, folderNameFragment + fileName);
        return modelPath;
    }
    else
    {
        // Try subfolders
        foreach (String folder in folders)
        {
            ModelPath modelPath = FindWSAPIModelPathOnServer(app, hostId, folder, fileName);
            if (modelPath != null)
                return modelPath;
        }
    }

    return null;
}

// This string is different for each RevitServer version
private static string s_revitServerVersion = "/RevitServerAdminRESTService2014/AdminRESTService.svc/";

/// <summary>
/// Connect to server to get list of available models and return server response
/// </summary>
private static XmlDictionaryReader GetResponse(Application app, string hostId, string info)
{
    // Create request	
    WebRequest request = WebRequest.Create("http://" + hostId + s_revitServerVersion + info);
    request.Method = "GET";

    // Add the information the request needs

    request.Headers.Add("User-Name", app.Username);
    request.Headers.Add("User-Machine-Name", app.Username);
    request.Headers.Add("Operation-GUID", Guid.NewGuid().ToString());

    // Read the response
    XmlDictionaryReaderQuotas quotas =
        new XmlDictionaryReaderQuotas();
    XmlDictionaryReader jsonReader =
        JsonReaderWriterFactory.CreateJsonReader(request.GetResponse().GetResponseStream(), quotas);

    return jsonReader;
}

/// <summary>
/// Read through server response to find particular model
/// </summary>
private static bool FindModelInServerResponseJson(XmlDictionaryReader reader, string fileName)
{
    // Read through entries in this section
    while (reader.Read())
    {
        if (reader.NodeType == XmlNodeType.EndElement && reader.Name == "Models")
            break;

        if (reader.NodeType == XmlNodeType.Element && reader.Name == "Name")
        {
            reader.Read();
            String modelName = reader.Value;
            if (modelName.Equals(fileName))
            {
                // Match found, stop looping and return
                return true;
            }
        }
    }

    return false;
}

中央からアタッチ解除されたモデルを開く

アドインはワークシェアリングされたファイルで作業するが、永続的な変更を行う必要がない場合、中央ファイルからアタッチ解除したモデルを開くことができます。

コード領域: アタッチ解除されたモデルを開く

     
private static Document OpenDetached(Application application, ModelPath modelPath)
{
    OpenOptions options1 = new OpenOptions();

    options1.DetachFromCentralOption = DetachFromCentralOption.DetachAndDiscardWorksets;
    Document openedDoc = application.OpenDocumentFile(modelPath, options1);

    return openedDoc;
}
下の例は、アプリケーションにサーバ ファイルへの読み取り専用アクセスのみが必要な場合に、サーバ モデルをローカルにコピーして、アタッチ解除して開く方法を示しています。このコードは、前の例で使用したメソッドを再利用している点に注意してください。

コード領域: アタッチ解除されたモデルをコピーして開く

public static Document CopyAndOpenDetached(UIApplication uiApp)
{
    // Copy a server model locally and open detached
    Application application = uiApp.Application;
    String hostId = application.GetRevitServerNetworkHosts().First();

    // Try to get the server path for the particular model on the server
    String rootFolder = "|";
    ModelPath serverPath = FindWSAPIModelPathOnServer(application, hostId, rootFolder, "ServerModel.rvt");

    // For debugging
    String sourcePath = ModelPathUtils.ConvertModelPathToUserVisiblePath(serverPath);

    // Setup the target location for the copy
    ModelPath localPath = GetWSAPIModelPath("CopiedModel.rvt");

    // Copy, allowing overwrite
    application.CopyModel(serverPath, ModelPathUtils.ConvertModelPathToUserVisiblePath(localPath), true);

    // Open the copy as detached
    Document openedDoc = OpenDetached(application, localPath);

    return openedDoc;
}