Chuyển đến nội dung
Diễn đàn CADViet
Đăng nhập để thực hiện theo  
Tue_NV

Tính tổng có điều kiện để thống kê thép cường độ cao

Các bài được khuyến nghị

Lời đầu tiên xin cho phép mình gửi lời cảm ơn tới diễn đàn CADVIET, gửi lời cảm ơn tới tất cả mọi người. Ở đay mình cảm thấy rất vui vì đã học hỏi rất nhiều điều bổ ích.

 

Mình có 1 vấn đề trong việc thống kê và tổng hợp cốt thép cường độ cao.

Đường kính của cốt thép cường độ cao vừa có đường kính lẻ, vừa có đường kính là số thập phân. Nó không giống như cốt thép thường.

Đây là file đính kèm :

Bảng chuyển đổi thép cường độ cao

Việc thống kê cốt thép cường độ cao thì mình đã tính toán được rồi.

Nhưng đến giai đoạn tổng hợp cốt thép cường độ cao thì mới gặp vấn đề. Mình phải ngồi tính tổng (SUM) trọng lượng của từng loại đường kính thép (như trên đã nói vừa là đường kính lẻ, vừa đường kính số thập phân) nên rất mất nhiều thời gian.

 

Xin các anh em trên diễn đàn CADVIET có thể viét nên một đoạn Code để tính tổng có điều kiện như thế này được không? Nó từa tựa như hàm Sumif trong Excel

 

Mình có 2 cột số :

Cột thứ nhất là cột ghi giá trị đường kính.

Cột thứ hai chính là trọng lượng của cốt thép cường độ cao.

Khi mình chạy Code thì chương trình yêu cầu :

Kết quả đầu vào :

- Nhập cột số thứ nhất (là cột đường kính ).

- Nhập cột số thứ hai (là cột trọng lượng thép cường độ cao).

- Nhập đường kính thép cần tính tổng (chính là một đường kính fi nằm trong cột thứ nhất).

Kết quả đầu ra : Cho ra giá trị tính tổng trọng lượng của giá trị đường kính fi trong cột thứ nhất.

 

Mong mọi người bỏ ít thời gian để quan tâm đến vấn đề này. Vì xu hướng ngày nay sử dụng thép cường độ cao càng nhiều. Nếu ai đó trên diễn đàn viết được chương trình thống kê cốt thép cường độ cao (Với mọi giá trị đường kính) thì cực kì tốt.

 

Xin cảm ơn mọi người. Chúc mọi người sức khỏe.

Chia sẻ bài đăng này


Liên kết tới bài đăng
Chia sẻ trên các trang web khác
Xin các anh em trên diễn đàn CADVIET có thể viét nên một đoạn Code để tính tổng có điều kiện như thế này được không? Nó từa tựa như hàm Sumif trong Excel

 

Mình có 2 cột số :

Cột thứ nhất là cột ghi giá trị đường kính.

Cột thứ hai chính là trọng lượng của cốt thép cường độ cao.

Khi mình chạy Code thì chương trình yêu cầu :

Kết quả đầu vào :

- Nhập cột số thứ nhất (là cột đường kính ).

- Nhập cột số thứ hai (là cột trọng lượng thép cường độ cao).

- Nhập đường kính thép cần tính tổng (chính là một đường kính fi nằm trong cột thứ nhất).

Kết quả đầu ra : Cho ra giá trị tính tổng trọng lượng của giá trị đường kính fi trong cột thứ nhất.

Chưa hiểu ý!

1. Cột thứ nhất và cột thứ hai trong diễn giải của bạn là cột nào trong file excel bạn đã post?

2. Bạn muốn thực hiện trong excel hay dùng lisp trong AutoCAD? Nếu là lisp, các "cột số" như bạn mô tả là loại đối tượng gì?

Chia sẻ bài đăng này


Liên kết tới bài đăng
Chia sẻ trên các trang web khác
Chưa hiểu ý!

1. Cột thứ nhất và cột thứ hai trong diễn giải của bạn là cột nào trong file excel bạn đã post?

2. Bạn muốn thực hiện trong excel hay dùng lisp trong AutoCAD? Nếu là lisp, các "cột số" như bạn mô tả là loại đối tượng gì?

Cảm ơn bác SSG đã hồi âm.

Ý của em là dùng Lisp trong AutoCAD.

Cột số của em ở đây là đối tượng Text

Em sẽ gửi một file CAD để minh họa :

Thống kê và tổng hợp cốt thép cường độ caoKết quả đầu vào :

- Nhập cột số thứ nhất (là cột đường kính ).

- Nhập cột số thứ hai (là cột trọng lượng thép cường độ cao).

- Nhập đường kính thép cần tính tổng (chính là một đường kính fi nằm trong cột thứ nhất).

Kết quả đầu ra : Cho ra giá trị tính tổng trọng lượng của giá trị đường kính fi trong cột thứ nhất (nằm trong bảng tổng hợp cốt thép)

 

Cảm ơn bác SSG nhiều lắm.

Chia sẻ bài đăng này


Liên kết tới bài đăng
Chia sẻ trên các trang web khác

Hiểu rồi. Bạn dùng hàm sumif như sau:

(defun sumif (L1 L2 v1 / i x Sum)
(setq i 0 Sum 0)
(foreach x L1
   (if (= x v1) (setq Sum (+ Sum (nth i L2))))
   (setq i (1+ i))
)
Sum
)

 

Diễn giải:

L1, L2 là list chứa các số thực (real)

v1 là 1 giá trị (phần tử) nào đó trong L1

sumif return kết quả sum các phần tử trong L2, tương ứng với v1

Ví dụ:

(setq L1 (list 1 2 3 1))

(setq L2 (list 10 20 30 10))

(sumif L1 L2 1) -> return 10 + 10 = 20

 

Trình tự thực hiện:

1. Dùng ssget chọn cột text1, convert sang list các số thực -> L1

2. Tương tự với cột text2 -> L2

3. Tính sumif theo L1, L2 và giá trị V1 (đường kính cần quan tâm) do user nhập, chuyển sang text và ghi kết quả

 

Hy vọng bạn tự làm được. Vướng chỗ nào ssg sẽ hỗ trợ thêm.

Chia sẻ bài đăng này


Liên kết tới bài đăng
Chia sẻ trên các trang web khác

Để bảo đảm tính thứ tự các thành phần trong cột 1 và 2, bổ sung vào trình tự thực hiện như sau:

1.

a- Dùng ssget chọn cột text1

b- Convert sang list oí text. Sắp xếp theo thứ tự tung độ giảm dần (dùng vl-sort)

c- Convert sang list các số thực

 

2. Tương tự 1

 

3. Không đổi

 

Ngoài ra, bạn có thể làm hàng loạt cho các giá trị trong cột 1 (không cần user nhập đường kính) bằng cách dùng hàm SumSpec như sau:

(defun SumSpec(L1 L2 / i Res v1 v2 old) ;;;Sum Special
(setq i 0)
(foreach v1 L1
   (setq v2 (nth i L2))
   (if (setq old (assoc v1 Res))
       (setq Res (subst (cons v1 (+ v2 (cdr old))) old Res))
       (setq Res (append Res (list (cons v1 v2))))
   )
   (setq i (1+ i))
)
Res
)

 

Kết quả trả về là một association list (danh sách kết hợp). Mỗi phần tử là một dotted pair (danh sách cặp có dấu chấm).

- Thành phần đầu của dotted pair là phần tử (đại diện, nếu có hơn 1 phần tử giống nhau) trong L1.

- Thành phần 2 là tổng tương ứng trong L2

 

Ví dụ:

(setq L1 (list 1 2 3 1 1))

(setq L2 (list 10 20 30 10 10))

(sumspec l1 l2) -> return ((1 . 30) (2 . 20) (3 . 30))

Đây là kết quả tổng hợp. Chẳng hạn, (1 . 30) có nghĩa là loại có giá trị là 1 trong L1 sẽ có tổng số là 30 tương ứng trong L2...

 

Cái này hơi phức tạp hơn một chút. Nhưng khi đã hiểu bạn sẽ thấy nó cũng bình thường. Điều quan trọng là hiệu quả sử dụng cao hơn nhiều. Bạn chỉ cần user quét chọn lần lượt 2 cột text, chương trình sẽ cho ra luôn bảng tổng hợp thống kê tất cả các loại đường kính có trong cột 1, kèm theo giá trị sum cho từng loại mà không cần buộc user phải nhập lần lượt từng đường kính.

Chỉnh sửa theo ssg

Chia sẻ bài đăng này


Liên kết tới bài đăng
Chia sẻ trên các trang web khác

Thống nhất quan điểm: ssg hỗ trợ, bạn tự xây dựng chương trình. OK?

 

Về convert từ ss sang list, mình tưởng rằng bạn đã biết vì có rất nhiều chương trình lisp post trên diễn đàn đã dùng kiểu như vậy. Đây là code của anh Hoành đưa lên lần đầu trên diễn đàn, rất nhiều mem chúng ta đã dùng nó như là tài sản chung của CADVIET:

;;;------------------------------------------------
(defun ss2ent(ss / sodt index ent lstent)
(setq
   sodt (if ss (sslength ss) 0)
   index 0
)
(repeat sodt
   (setq
       ent (ssname ss index)
       index (1+ index)
       lstent (cons ent lstent)
   )
)
(reverse lstent)
)
;;;------------------------------------------------

 

Diễn giải:

1. List Data Type là kiểu dữ liệu cơ bản của ngôn ngữ Lisp. Người ta đã cung cấp sẵn rất nhiều hàm thao tác với list. Mọi trường hợp, cảm thấy xử lý cái gì đó khó khăn, hãy nghĩ ngay đến việc chuyển chung về dạng List, bạn sẽ có lời giải rất đơn giản.

2. Kết quả gọi hàm ssget là một Selection Set (tập hợp thực thể). Thao tác trực tiếp với ss có rất nhiều hạn chế vì có rất ít hàm có sẵn của AutoLisp thao tác trực tiếp với chúng. Hàm ss2ent sẽ chuyển toàn bộ các entity trong ss sang kiểu list -> bạn tha hồ chọn các hàm có sẵn của Lisp để xử lý.

 

Ssg đề nghị, tạm thời bạn hãy hoàn chỉnh chương trình theo phương án 1 (làm lần lượt từng cái, user nhập đường kính). Khi đã OK, thử làm theo phương án "hàng loạt" như ssg vừa post. Cứ yên tâm, ssg sẽ hỗ trợ bạn tối đa.

Chúc thành công.

Chia sẻ bài đăng này


Liên kết tới bài đăng
Chia sẻ trên các trang web khác
Để bảo đảm tính thứ tự các thành phần trong cột 1 và 2, bổ sung vào trình tự thực hiện như sau:

1.

a- Dùng ssget chọn cột text1

b- Sắp xếp theo thứ tự tung độ giảm dần (dùng vl-sort)

c- Convert sang list các số thực

Ở bước b (dùng vl-sort) và bước c : Convert sang list các số thực : Quả thật em chưa biết.

Mong bác SSG hướng dẫn thêm

 

Ví dụ:

(setq L1 (list 1 2 3 1 1))

(setq L2 (list 10 20 30 10 10))

(sumspec l1 l2) -> return ((1 . 30) (2 . 20) (3 . 30))

Đây là kết quả tổng hợp. Chẳng hạn, (1 . 30) có nghĩa là loại có giá trị là 1 trong L1 sẽ có tổng số là 30 tương ứng trong L2...

 

Ví dụ này thì em hiểu bác ạ. Tức là kết quả sẽ là : giá trị 1 trong L1 sẽ có 3 giá trị tương ứng ở L2 : tức là 3 giá trị 10,10,10

Lấy 3 giá trị 10 cộng với nhau : 10+10+10=30.

 

Nhưng em chưa biết cách xuất dữ liệu ra như thế nào bác ạ. Mong bác chỉ giúp.

Chia sẻ bài đăng này


Liên kết tới bài đăng
Chia sẻ trên các trang web khác
Ở bước b (dùng vl-sort) và bước c : Convert sang list các số thực : Quả thật em chưa biết.

1. Hàm atof sẽ chuyển string sang real

2. Vl-sort... chà, nếu quả thật chưa biết thì hơi gay. Thôi được, tạm thời bạn hãy xem Help, đọc sách hoặc search trên diễn đàn. Mình sẽ quay lại sau. Giờ mình có việc rồi, điện thoại của sếp đang réo!

Chia sẻ bài đăng này


Liên kết tới bài đăng
Chia sẻ trên các trang web khác

Bạn chạy thử lisp sau, lệnh VD:

;;;---------------------------------------------------
(defun ss2ent(ss / sodt index ent lstent) ;;;Convert ss to list of entities
(setq
   sodt (if ss (sslength ss) 0)
   index 0
)
(repeat sodt
   (setq
       ent (ssname ss index)
       index (1+ index)
       lstent (cons ent lstent)
   )
)
(reverse lstent)
)
;;;---------------------------------------------------
(defun SumSpec(L1 L2 / i Res v1 v2 old) ;;;Sum Special
(setq i 0)
(foreach v1 L1
   (setq v2 (nth i L2))
   (if (setq old (assoc v1 Res))
       (setq Res (subst (cons v1 (+ v2 (cdr old))) old Res))
       (setq Res (append Res (list (cons v1 v2))))
   )
   (setq i (1+ i))
)
Res
)
;;;---------------------------------------------------
(defun Upper (e1 e2) ;;;Return T if e1 upper e2, otherwise return nil
(> (cadr (cdr (assoc 10 (entget e1)))) (cadr (cdr (assoc 10 (entget e2)))))
)
;;;---------------------------------------------------
(defun Ent2Real(Le / e Lr) ;;;Convert list of text entities to list of real
(foreach e Le (setq Lr (append Lr (list (atof (cdr (assoc 1 (entget e))))))))
)
;;;---------------------------------------------------
(defun C:VD( / ss1 ss2 L1 L2 Res Temp x)
(prompt "\nChon cac text o cot duong kinh...")
(setq ss1 (ssget '((0 . "TEXT"))))
(prompt "\nChon cac text o cot khoi luong...")
(setq ss2 (ssget '((0 . "TEXT"))))
(setq
   L1 (ent2real (vl-sort (ss2ent ss1) 'Upper))
   L2 (ent2real (vl-sort (ss2ent ss2) 'Upper))
   Res (sumspec L1 L2)
   Temp ""
)
(foreach x Res (setq Temp (strcat Temp "\nD = " (rtos (car x)) " -> " (rtos (cdr x)) " kg")))
(alert Temp)
)
;;;---------------------------------------------------
;;;That is a example only! Replace alert by other, according your purpose...
;;;Maybe you should add check conditions for input data if necessary...
;;;Success!
;;;---------------------------------------------------

 

Đề nghị:

1. Phân tích kỹ các code sử dụng trong các functions con và cách áp dụng chúng trong chương trình chính. Nếu thấy hơi khó hiểu, thử làm vài ví dụ đơn giản áp dụng các function con, bạn sẽ hiểu ra vấn đề.

2. Kết quả tổng hợp nằm trong biến Res. Hàm alert chỉ là ví dụ thể hiện kết quả. Bạn hãy tìm cách chuyển data trong Res theo mục đích và cách thức trình bày kết quả của bạn. Tham khảo cách tạo nên giá trị của biến Temp sau khi kết thúc vòng foreach sẽ rất hữu ích.

3. Bài này là một trong những "cột mốc" quan trọng trong quá trình "làm chủ AutoLisp". Vượt qua nó, bạn sẽ có một nền tảng kiến thức Lisp khá vững chắc để có thể tạo nên những ứng dụng hiệu quả. Hãy cố lên!

Chia sẻ bài đăng này


Liên kết tới bài đăng
Chia sẻ trên các trang web khác
Bạn chạy thử lisp sau, lệnh VD:

;;;---------------------------------------------------
(defun ss2ent(ss / sodt index ent lstent) ;;;Convert ss to list of entities
(setq
   sodt (if ss (sslength ss) 0)
   index 0
)
(repeat sodt
   (setq
       ent (ssname ss index)
       index (1+ index)
       lstent (cons ent lstent)
   )
)
(reverse lstent)
)
;;;---------------------------------------------------
(defun SumSpec(L1 L2 / i Res v1 v2 old) ;;;Sum Special
(setq i 0)
(foreach v1 L1
   (setq v2 (nth i L2))
   (if (setq old (assoc v1 Res))
       (setq Res (subst (cons v1 (+ v2 (cdr old))) old Res))
       (setq Res (append Res (list (cons v1 v2))))
   )
   (setq i (1+ i))
)
Res
)
;;;---------------------------------------------------
(defun Upper (e1 e2) ;;;Return T if e1 upper e2, otherwise return nil
(> (cadr (cdr (assoc 10 (entget e1)))) (cadr (cdr (assoc 10 (entget e2)))))
)
;;;---------------------------------------------------
(defun Ent2Real(Le / e Lr) ;;;Convert list of text entities to list of real
(foreach e Le (setq Lr (append Lr (list (atof (cdr (assoc 1 (entget e))))))))
)
;;;---------------------------------------------------
(defun C:VD( / ss1 ss2 L1 L2 Res Temp x)
(prompt "\nChon cac text o cot duong kinh...")
(setq ss1 (ssget '((0 . "TEXT"))))
(prompt "\nChon cac text o cot khoi luong...")
(setq ss2 (ssget '((0 . "TEXT"))))
(setq
   L1 (ent2real (vl-sort (ss2ent ss1) 'Upper))
   L2 (ent2real (vl-sort (ss2ent ss2) 'Upper))
   Res (sumspec L1 L2)
   Temp ""
)
(foreach x Res (setq Temp (strcat Temp "\nD = " (rtos (car x)) " -> " (rtos (cdr x)) " kg")))
(alert Temp)
)
;;;---------------------------------------------------
;;;That is a example only! Replace alert by other, according your purpose...
;;;Maybe you should add check conditions for input data if necessary...
;;;Success!
;;;---------------------------------------------------

 

Đề nghị:

1. Phân tích kỹ các code sử dụng trong các functions con và cách áp dụng chúng trong chương trình chính. Nếu thấy hơi khó hiểu, thử làm vài ví dụ đơn giản áp dụng các function con, bạn sẽ hiểu ra vấn đề.

2. Kết quả tổng hợp nằm trong biến Res. Hàm alert chỉ là ví dụ thể hiện kết quả. Bạn hãy tìm cách chuyển data trong Res theo mục đích và cách thức trình bày kết quả của bạn. Tham khảo cách tạo nên giá trị của biến Temp sau khi kết thúc vòng foreach sẽ rất hữu ích.

3. Bài này là một trong những "cột mốc" quan trọng trong quá trình "làm chủ AutoLisp". Vượt qua nó, bạn sẽ có một nền tảng kiến thức Lisp khá vững chắc để có thể tạo nên những ứng dụng hiệu quả. Hãy cố lên!

Rất chân thành cảm ơn bác SSG. Em sẽ cố gắng nghiên cứu bài học cột mốc quý giá này để tạo nên những ứng dụng hiệu quả nhờ AutoLisp.

Chia sẻ bài đăng này


Liên kết tới bài đăng
Chia sẻ trên các trang web khác

Các bạn cadviet có thể viết cho tôi 1 lisp chọn một bề mặt ngẫu nhiên(đối tượng kính) sau đó cho ra lựa chọn vật liệu là nhôm, thép, kính và tiếp đó là lựa chọn chiều dài hoặc dầy để cho ra 1 kết quả text là khối lượng của khối đó tính bằng (Kg) chân thành cảm ơn anh e tối rất cần lisp nay.

Chia sẻ bài đăng này


Liên kết tới bài đăng
Chia sẻ trên các trang web khác

Tạo một tài khoản hoặc đăng nhập để nhận xét

Bạn cần phải là một thành viên để lại một bình luận

Tạo tài khoản

Đăng ký một tài khoản mới trong cộng đồng của chúng tôi. Điều đó dễ mà.

Đăng ký tài khoản mới

Đăng nhập

Bạn có sẵn sàng để tạo một tài khoản ? Đăng nhập tại đây.

Đăng nhập ngay

Đăng nhập để thực hiện theo  

×