Ở các dự án lớn đôi khi khách hàng cần dõi sự thay đổi revision của các đám mây. Tuy nhiên ở bản thống kê sheet list trong revit, chỉ có revision hiện tại hay mới nhất trên tờ sheet mới được hiển thị. Có nghĩa là, chúng ta không thể có được lịch sử sửa đổi đám mây của sheet hay view cụ thể từ Revit.
Cách thủ công/cùi bắp để giải quyết là chỉ định một ai đó đi kiểm tra revision của đám mây trên từng mặt bằng và gom lại thành một danh sách trong excel.
May mắn thay chúng ta có thể truy cập vào tất cả các revision của đám mây thông qua Revit API và xuất chúng bao gồm cả dữ liệu revision liên quan. Chúng ta sẽ xuất dữ liệu của clouds này ở mỗi giai đoạn nhất định của dự án.
Lấy Id của các Revisions
Import thư viện vào trước, ở đây BCDD dùng cú pháp “as + tên viết tắt của class” để code về sau nó ngắn gọn hơn. Thay vì phải gõ FilteredElementCollector thì chúng ta chỉ cần gõ Fec, thay vì phải gõ BuiltInCategory thì chúng ta sẽ dùng Bic.
import clr
clr.AddReference("RevitAPI")
from Autodesk.Revit.DB import BuiltInCategory as Bic
from Autodesk.Revit.DB import FilteredElementCollector as Fec
doc = __revit__.ActiveUIDocument.Document
rev_clouds = Fec(doc).OfCategory(Bic.OST_RevisionClouds).WhereElementIsNotElementType().ToElements()
Sau khi Run chúng ta có revision cloud, để ý thì thấy rằng revision ở trong một list (dù chỉ có một revision).

Sau khi có revision cloud, chúng ta có thể truy cập phần thông tin hữu ích nhất của một đối tượng: đó là Id. Chạy một vòng lặp for để in ra Id

Đọc dữ liệu của đối tượng
Khi chúng ta xử lý từng revision cloud riêng lẻ trong vòng lặp loop, chúng ta có thể bắt đầu lấy properties và parameters của chúng. Properties và parameters thì giống nhau, mặc dù cái cách mà chúng ta lấy giá trị của chúng thì khác nhau. Properties thì truy cập trực tiếp ví dụ như sau .RevisionId hay .OwnerViewId. Đây đều là những thông tin hữu ích vì chúng ta sẽ biết được đám mây này thuộc về bản sửa đổi nào hay nó được đặt trên view nào.
Tuy nhiên chúng ta chỉ nhận được Ids của những đối tượng được trả lại. Vậy làm thế nào chúng ta nhận lại các đối tượng thực từ Id?
Ngay sau khi chúng ta truy cập vào đối tượng thực, chúng ta có thể truy xuất Name của chúng để có đầu ra rõ nghĩa hơn.

Phát triển thêm tí nửa, giờ BCDD chỉ lấy phần số thông qua thuộc tính.IntegerValue từ Id của đối tượng và chuyển chúng sang định dạng text luôn thông qua tính năng str(),vì chúng ta dự định tí nửa sẽ viết chúng ra một file text.

Tới đây thì chúng ta đã có 3 thông tin quan trọng rồi, đó là id của revision, view của revision và tên của Revision. Và đến đây chúng ta cũng đã truy cập được thuộc tính của đối tượng nhưng chúng ta chưa xem xét việc truy cập vào tham số (một trong những công việc phổ biến khi làm việc với Revit API). Nếu đã đọc qua các bài trước, có thể bạn đã biết là thông qua .LookupParameter(“parameter name”) chúng ta có thể truy cập tham số.
Nhưng điều đó chỉ giúp chúng ta có tham số chứ chưa có được giá trị của tham số đó. Để có được giá trị của tham số chúng ta cần có thêm method (phương thức), và nó phụ thuộc vào loại dữ liệu của tham số. BCDD sẽ truy cập vào tham số “Comments” của revision cloud, được lưu trữ dưới định dạng text, phương thức chúng ta sử dụng để lấy giá trị của tham số là .AsString()

Nếu chúng ta nhận None (nghĩa là không có gì) ở đầu ra, khi mà không có dữ liệu cho tham số của revision cloud. Dĩ nhiên là chúng ta không thích None xuất hiện trong danh sách đầu ra nên sẽ dùng dòng code sau trong Python để cho ra một chuỗi rỗng khi nó phát hiện ra None.
comment = cloud.LookupParameter("Comments").AsString() or ""

Kết quả như các bạn thấy đấy, Revision đầu tiên cho ra kết quả BCDD trong khi revision thứ hai cho ra giá trị rỗng.
Xuất dữ liệu ra csv
Tạo file csv
Cú pháp như sau:
with open("d:/rev_clouds.csv", "w") as rev_csv:

Sau khi Run là chúng ta có file csv trong thư mục như sau

Lấy dữ liệu revision
Chúng ta có thể lấy tất cả các loại dữ liệu từ revision. Điều đó phụ thuộc vào thiết lập của dự án như dự án sử dụng revision “Per Project” hay là “Per Sheet”. Trong phạm vi bài viết này chúng ta sẽ sử dụng revision date từ thuộc tính .RevisionDate

Thêm hai thông tin chúng ta cần lấy là sheet number và sheet name. Kiểm tra nhanh trên RevitPythonShell

Ở trên chỉ là kiểm tra trong trường hợp chỉ có 1 view nằm trên sheet thôi, cực kỳ đơn giản. Nhưng giờ nếu Run trong một file lớn hơn thì chúng ta bị lỗi sau: ’NoneType’ object has no attribute ‘AsString()’

Điều này về cơ bản có nghĩa là chúng ta không thể sử dụng .AsString() để lấy dữ liệu text từ tham số, nếu đối tượng đó không tồn tại. Ví dụ như view có chứa revision cloud nhưng không được đặt trên sheet nên sẽ không có giá trị trong tham số Sheet Name vs Sheet Number.
Vì vậy để đề phòng trường hợp view không nằm trên sheet thì chúng ta viết thêm dòng else cho câu điều kiện if như sau:

Xuất dữ liệu ra csv
Tiến hành gom lại hết các thông tin chúng ta có của revision cloud thành một list vào một biến gọi là info. Tất cả các thông tin của mỗi một revision cloud nên được ghi vào một dòng ở csv, vì vậy chúng ta gom lại thông tin đơn lẽ của các đối tượng từ info với dấu ;
Với một dòng code đơn giản rev_csv.write(content + “\n”) chúng ta có thể viết nội dung text vào csv, “\n” để chắc rằng cứ mỗi lần chạy trong vòng lặp nó viết ra mỗi dòng.

Full code như sau:
import clr
clr.AddReference("RevitAPI")
from Autodesk.Revit.DB import BuiltInCategory as Bic
from Autodesk.Revit.DB import FilteredElementCollector as Fec
doc = __revit__.ActiveUIDocument.Document
rev_clouds = Fec(doc).OfCategory(Bic.OST_RevisionClouds).WhereElementIsNotElementType().ToElements()
with open("d:/rev_clouds.csv", "w") as rev_csv:
csv_header = "sheet_number;sheet_name;view_name;rev_cloud_id;revision;comment;date"
rev_csv.write(csv_header + "\n")
for cloud in rev_clouds:
print(35 * "-")
cloud_id = str(cloud.Id.IntegerValue)
view = doc.GetElement(cloud.OwnerViewId)
cloud_revision = doc.GetElement(cloud.RevisionId)
view_name = view.Name
# cloud view on sheet or is sheet
if view.LookupParameter("Sheet Name"):
sheet_name = view.LookupParameter("Sheet Name").AsString()
sheet_number = view.LookupParameter("Sheet Number").AsString()
# cloud view not on sheet
else:
sheet_name = "no_sheet_name_found"
sheet_number = "no_sheet_number_found"
comment = cloud.LookupParameter("Comments").AsString() or ""
cloud_comment = comment.replace('\r\n', '')
info = [sheet_number,
sheet_name,
view_name,
cloud_id,
cloud_revision.Name,
cloud_revision.RevisionDate,
cloud_comment,
]
print(info)
cloud_info = ";".join(info)
rev_csv.write(cloud_info + "\n")
Ngoài BIM ra, thì BCDD có phân phối Cafe chất lượng cao với chi phí hợp lý. Uống Cafe để tỉnh táo và năng lượng hơn trên đường đời bạn nhé. Tìm hiểu thêm về Cafe tại đây.
Nếu thấy Nếu thấy bài viết này hữu ích, hãy cân nhắc việc follow BCDD tại đây
Bài viết do admin 1 Nghia Nguyen và cộng sự BCDD biên soạn.
Tài liệu tham khảo (reference source): pure_Revit_Python của tác giả Frederic Beaupere, Herzog & de Meuron – DBEI BILT Materials