Lấy giá trị tuần tự liên tục trong 1 cột! (1 người xem)

Liên hệ QC

Người dùng đang xem chủ đề này

alias1313

Thành viên hoạt động
Tham gia
7/4/17
Bài viết
163
Được thích
13
Em cần lấy giá trị trong một cột ( >1000 hàng) bằng cách sử dụng VBA, mong các anh giúp đỡ!

Qui luật để lấy như sau:
Tai cột E
- Giá trị đầu tiên > 50 lấy, gán giá trị ra ô excel cột G
- Giá trị tiếp theo < 50 lấy, gán giá trị ra ô excel tiếp theo ô trên
- Giá trị tiếp theo > 50 lấy
- Giá trị tiếp theo < 50 lấy.

Cứ lấy xen kẽ như vậy! Giá trị lấy được gán ra cột G.
Em viết 1 đoạn code như bên dưới, nhưng em không biết muốn lấy giá trị tiếp theo phải viết thế nào để hàm for nó hiểu.
Mong các anh giúp em! Em cảm ơn!

Mã:
Sub LocGiaTri()

   Dim range1 as range

For each range1 in Range("E1:E20")

If range1.value > 50 then

End if

Next range1

End sub
 

File đính kèm

Em cần lấy giá trị trong một cột ( >1000 hàng) bằng cách sử dụng VBA, mong các anh giúp đỡ!

Qui luật để lấy như sau:
Tai cột E
- Giá trị đầu tiên > 50 lấy, gán giá trị ra ô excel cột G
- Giá trị tiếp theo < 50 lấy, gán giá trị ra ô excel tiếp theo ô trên
- Giá trị tiếp theo > 50 lấy
- Giá trị tiếp theo < 50 lấy.

Cứ lấy xen kẽ như vậy! Giá trị lấy được gán ra cột G.
Em viết 1 đoạn code như bên dưới, nhưng em không biết muốn lấy giá trị tiếp theo phải viết thế nào để hàm for nó hiểu.
Mong các anh giúp em! Em cảm ơn!

Mã:
Sub LocGiaTri()

   Dim range1 as range

For each range1 in Range("E1:E20")

If range1.value > 50 then

End if

Next range1

End sub
Số đúng = 50 cũng không lấy hả bạn?
 
Upvote 0
Em cần lấy giá trị trong một cột ( >1000 hàng) bằng cách sử dụng VBA, mong các anh giúp đỡ!

Qui luật để lấy như sau:
Tai cột E
- Giá trị đầu tiên > 50 lấy, gán giá trị ra ô excel cột G
- Giá trị tiếp theo < 50 lấy, gán giá trị ra ô excel tiếp theo ô trên
- Giá trị tiếp theo > 50 lấy
- Giá trị tiếp theo < 50 lấy.

Cứ lấy xen kẽ như vậy! Giá trị lấy được gán ra cột G.
Em viết 1 đoạn code như bên dưới, nhưng em không biết muốn lấy giá trị tiếp theo phải viết thế nào để hàm for nó hiểu.
Mong các anh giúp em! Em cảm ơn!

Mã:
Sub LocGiaTri()

   Dim range1 as range

For each range1 in Range("E1:E20")

If range1.value > 50 then

End if

Next range1

End sub
Bạn kiểm tra xem đúng không
Mã:
Sub aa()
    Dim i, lonhon
    Cells(4, 7) = Cells(4, 5)
    If Cells(4, 5) > 50 Then lonhon = True
    For i = 5 To 17
        If Cells(i, 5) > 50 Then
            If lonhon = False Then
                lonhon = True
                Cells(i, 7) = Cells(i, 5)
            End If
        Else
            If lonhon Then
                lonhon = False
                Cells(i, 7) = Cells(i, 5)
            End If
        End If
    Next
End Sub
 
Upvote 0
Mã:
sub vidu()
Const N as long =50
Dim a(), b(), s,i as long, j as long, flag as boolean
a= sheet1.range("e1:e20").value
Redim b(1 to ubound(a,1),1 to 1)
flag=true
For i=1 to ubound(a,1) step 1
s=a(i,1)
If isnumeric(s)=true then
If (s>=N)=flag then
flag=not flag
j=j+1
b(j,1)=s
End if
End if
Next i
Sheet1.range("g1").resize(j,1)=b
End sub
. Viết chay trên điện thoại nên hơi xấu chút. :)
 
Lần chỉnh sửa cuối:
Upvote 0
Mã:
sub vidu()
Const N as long =50
Dim a(), b(), s,i as long, j as long, flag as boolean
a= sheet1.range("e1:e20").value
Redim b(1 to ubound(a,1),1 to 1)
flag=true
For i=1 to ubond(a,1) step 1
s=a(i,1)
If isnumeric(s)=true then
If (s>=N)=flag then
flag=not flag
j=j+1
b(j,1)=s
End if
End if
Next i
Sheet1.range("g1").resize(j,1)=b
End sub
. Viết chay trên điện thoại nên hơi xấu chút. :)
Trường hợp bài này bạn không cần phải flag lớn hay nhỏ. Chỉ cần xét xem hiện tại số kết quả là chẵn hay lẻ.
 
Upvote 0
Mã:
sub vidu()
Const N as long =50
Dim a(), b(), s,i as long, j as long, flag as boolean
a= sheet1.range("e1:e20").value
Redim b(1 to ubound(a,1),1 to 1)
flag=true
For i=1 to ubound(a,1) step 1
s=a(i,1)
If isnumeric(s)=true then
If (s>=N)=flag then
flag=not flag
j=j+1
b(j,1)=s
End if
End if
Next i
Sheet1.range("g1").resize(j,1)=b
End sub
. Viết chay trên điện thoại nên hơi xấu chút. :)
Thiếu 1 chữ "u" đúng không Befaint?
 
Upvote 0
Dạ em quên: lấy >= 50.

Mong Thầy giúp em! Em cảm ơn Thầy!
Viết vầy:
Mã:
Sub Test()
  Dim arr
  Dim idx As Long
  Dim bChk As Boolean
  arr = Sheet1.Range("E4:E1000").Value
  ReDim aRes(1 To UBound(arr), 1 To 1)
  For idx = 1 To UBound(arr)
    If arr(idx, 1) <> Empty Then
      If bChk = (arr(idx, 1) < 50) Then
        aRes(idx, 1) = arr(idx, 1)
        bChk = Not bChk
      End If
    End If
  Next
  Sheet1.Range("G4:G1000").Value = aRes
End Sub
 
Upvote 0
Bạn kiểm tra xem đúng không
Mã:
Sub aa()
    Dim i, lonhon
    Cells(4, 7) = Cells(4, 5)
    If Cells(4, 5) > 50 Then lonhon = True
    For i = 5 To 17
        If Cells(i, 5) > 50 Then
            If lonhon = False Then
                lonhon = True
                Cells(i, 7) = Cells(i, 5)
            End If
        Else
            If lonhon Then
                lonhon = False
                Cells(i, 7) = Cells(i, 5)
            End If
        End If
    Next
End Sub

Code anh giúp chạy hoàn hảo! Nhưng anh có thể giải thích giùm em các dòng code đc ko anh!
Em chưa gặp kiểu "lonhon = true" bao giờ nên xem mãi không hiểu cách code vận hành!
Mong anh giúp đỡ!
 
Upvote 0
Code anh giúp chạy hoàn hảo! Nhưng anh có thể giải thích giùm em các dòng code đc ko anh!
Em chưa gặp kiểu "lonhon = true" bao giờ nên xem mãi không hiểu cách code vận hành!
Mong anh giúp đỡ!
MÌnh hơi khó giải thích, tạm như thế này
số 5, 7 tức là cột E, G
for i = 5 to 17 tức là từ dòng 5 đến dòng 17
cells(i,5) tức là dòng i cột E ( i ở đâu nằm trong khoảng 5 - 17)
lonhon thì là lớn hơn, do xét liên tục nên mình dùng biến này để kiểm tra, nếu giá trị hiện tại lớn hơn 50 thì kiểm tra xem biến lonhon, nếu lớn hơn rồi thì không xét nữa nếu số trc điền là nhỏ hơn (lonhon = false) thì lấy giá trị. Xét cho trường hợp ngược lại
 
Upvote 0
Upvote 0
Viết vầy:
Mã:
Sub Test()
  Dim arr
  Dim idx As Long
  Dim bChk As Boolean
  arr = Sheet1.Range("E4:E1000").Value
  ReDim aRes(1 To UBound(arr), 1 To 1)
  For idx = 1 To UBound(arr)
    If arr(idx, 1) <> Empty Then
      If bChk = (arr(idx, 1) < 50) Then
        aRes(idx, 1) = arr(idx, 1)
        bChk = Not bChk
      End If
    End If
  Next
  Sheet1.Range("G4:G1000").Value = aRes
End Sub

Code chạy chính xác rồi thưa Thầy!
Thầy giúp em giải thích đoạn code dưới nha Thầy @ndu96081631 ! Em không hiểu đoạn đó!
Em thấy: (arr(idx, 1) = 34 thì bChk = (arr(idx, 1) < 50) = true, Nhưng nó lại ra False.
và : "bChk = Not bChk" để làm gì em cũng ko biết!
Mong Thầy giúp em!

Mã:
If bChk = (arr(idx, 1) < 50) Then

        aRes(idx, 1) = arr(idx, 1)

        bChk = Not bChk

      End If

Em cảm ơn Thầy rất nhiều!
Bài đã được tự động gộp:

Có thấy đúng đâu trời
???!!!
----------------------

lonhon chắc là lộn hòn. Mà lonhon = True có nghĩa là chắc chắn bị lộn hòn

Dạ! code bị nhầm nếu giá trị đầu tiên < 50, sẽ chạy ngược! hihi!
 
Upvote 0
Code chạy chính xác rồi thưa Thầy!
Thầy giúp em giải thích đoạn code dưới nha Thầy @ndu96081631 ! Em không hiểu đoạn đó!
Em thấy: (arr(idx, 1) = 34 thì bChk = (arr(idx, 1) < 50) = true, Nhưng nó lại ra False.
và : "bChk = Not bChk" để làm gì em cũng ko biết!
Mong Thầy giúp em!

Mã:
If bChk = (arr(idx, 1) < 50) Then

        aRes(idx, 1) = arr(idx, 1)

        bChk = Not bChk

      End If

Em cảm ơn Thầy rất nhiều!
- Đầu tiên bChk chưa có giá trị nên nó =False
- Vào vòng lập ta xét biểu thức (arr(idx, 1) < 50) sẽ cho kết quả =True (vì hiện arr(idx, 1) đang = 32) trong khi bChk đang =False. So sánh False =True sẽ ra kết quả sai (tức False) nên không thỏa điều kiện
- Chạy tiếp đến khi gặp giá trị 52 thì biểu thức (arr(idx, 1) < 50) sẽ cho kết quả =False trong khi bChk vẫn đang =False. So sánh False =False sẽ ra kết quả đúng (tức True) ---> Thỏa điều kiện ta lấy giá trị vào mảng đồng thời làm động tác bChk = Not bChk để "lật" giá trị bChk từ True thành False (hoặc từ False thành True)
- Cứ thế tiếp tục
vậy thôi
------------------------
. Có đúng đâu???
"gán giá trị ra ô excel tiếp theo ô trên"
Đang dùng điện thoại có xem được file không đấy? Lấy giá trị và gán ngang hàng với cell tương ứng, không phải lấy xong rồi dồn 1 cục đâu
 
Upvote 0
- Đầu tiên bChk chưa có giá trị nên nó =False
- Vào vòng lập ta xét biểu thức (arr(idx, 1) < 50) sẽ cho kết quả =True (vì hiện arr(idx, 1) đang = 32) trong khi bChk đang =False. So sánh False =True sẽ ra kết quả sai (tức False) nên không thỏa điều kiện
- Chạy tiếp đến khi gặp giá trị 52 thì biểu thức (arr(idx, 1) < 50) sẽ cho kết quả =False trong khi bChk vẫn đang =False. So sánh False =False sẽ ra kết quả đúng (tức True) ---> Thỏa điều kiện ta lấy giá trị vào mảng đồng thời làm động tác bChk = Not bChk để "lật" giá trị bChk từ True thành False (hoặc từ False thành True)
- Cứ thế tiếp tục
vậy thôi
------------------------

Đang dùng điện thoại có xem được file không đấy? Lấy giá trị và gán ngang hàng với cell tương ứng, không phải lấy xong rồi dồn 1 cục đâu


haha!...Em hiểu rồi...Cảm ơn Thầy @ndu96081631 rất nhiều ạ!
@befaint : Code chạy chính xác rồi Bác ơi! thử đổi giá trị các kiểu đều chạy tốt hêt! hihi!
 
Upvote 0
. Có đúng đâu???
"gán giá trị ra ô excel tiếp theo ô trên"

Giờ em mới thấy Code của anh! em đã test! và code chạy đúng theo kiểu: " gán giá trị ra ô excel tiếp theo ô trên"!
Cảm ơn anh rất nhiều!
Bài đã được tự động gộp:

Em cảm ơn Thầy @ndu96081631 cùng các anh rất nhiều!
Đã giúp em rất nhiều cách giải quyết vấn đề! Mặc dù chỉ vừa Post bài!
Mong Thầy và các anh luôn khỏe! hiihi!

Trân trọng!
Bài đã được tự động gộp:

MÌnh hơi khó giải thích, tạm như thế này
số 5, 7 tức là cột E, G
for i = 5 to 17 tức là từ dòng 5 đến dòng 17
cells(i,5) tức là dòng i cột E ( i ở đâu nằm trong khoảng 5 - 17)
lonhon thì là lớn hơn, do xét liên tục nên mình dùng biến này để kiểm tra, nếu giá trị hiện tại lớn hơn 50 thì kiểm tra xem biến lonhon, nếu lớn hơn rồi thì không xét nữa nếu số trc điền là nhỏ hơn (lonhon = false) thì lấy giá trị. Xét cho trường hợp ngược lại

Em cảm ơn anh nhiều!
 
Lần chỉnh sửa cuối:
Upvote 0
Mã:
Sub Test()
  Dim arr
  Dim idx As Long
  Dim bChk As Boolean
  arr = Sheet1.Range("E4:E1000").Value
  ReDim aRes(1 To UBound(arr), 1 To 1)
  For idx = 1 To UBound(arr)
    If arr(idx, 1) <> Empty Then
      If bChk = (arr(idx, 1) < 50) Then
        aRes(idx, 1) = arr(idx, 1)
        bChk = Not bChk
      End If
    End If
  Next
  Sheet1.Range("G4:G1000").Value = aRes
End Sub

Code trên khi chạy trên 1 sheet thì không sao, nhưng khi chạy trên nhiều sheet 1 lúc, thì bị tình trạng:
- Giá trị: bChk - cuối cùng của sheet1 tính sang cho sheet2 ( khi sang sheet2 phải reset lại biến bChr) => giá trị đầu tiên lấy bị sai ( lúc >50, lúc < 50)
- Em mò mãi mới thấy cách sửa đc lỗi này bằng cách thêm bChk = false để reset. và thấy khi chạy nhiều sheet kết quả vẫn đúng.
-Em muốn hỏi: đó có phải là cách reset biến Bolean không và cách đúng nhất là gì ạ!
Em cảm ơn Thầy cùng các anh!

Mã:
Dim arr

  Dim idx As Long

  Dim bChk As Boolean

  arr = Sheet1.Range("E4:E1000").Value

  ReDim aRes(1 To UBound(arr), 1 To 1)

  For idx = 1 To UBound(arr)

    If arr(idx, 1) <> Empty Then

      If bChk = (arr(idx, 1) < 50) Then

        aRes(idx, 1) = arr(idx, 1)

        bChk = Not bChk

      End If

    End If

  Next

  Sheet1.Range("G4:G1000").Value = aRes
  bChk = False
  End sub
 
Upvote 0
Gom 11 sheets rồi mới chạy code bài này. Tức là tối qua phải đăng bài gom 11 sheets trước, sáng nay đăng bài này.
Hoặc đăng một bài nêu hai yêu cầu luôn và ngồi chờ món súp cá thôi. :)
 
Upvote 0
Gom 11 sheets rồi mới chạy code bài này. Tức là tối qua phải đăng bài gom 11 sheets trước, sáng nay đăng bài này.
Hoặc đăng một bài nêu hai yêu cầu luôn và ngồi chờ món súp cá thôi. :)

Hihi! Đúng ra em muốn tự làm phần đó! Vì em nghĩ mình làm được! nhưng qua đến giờ em làm mãi ko được nên đành phải nhờ Thầy và các anh giúp!
Em cảm ơn anh!
 
Upvote 0
Hihi! Đúng ra em muốn tự làm phần đó! Vì em nghĩ mình làm được! nhưng qua đến giờ em làm mãi ko được nên đành phải nhờ Thầy và các anh giúp!
Em cảm ơn anh!
Chẳng phải bạn đã hỏi về việc tổng hợp 10 sheets vào 1 sheet ở đây sao:
https://www.giaiphapexcel.com/diend...thứ-tự-giảm-dần-vào-1-sheet-cuối-cùng.136668/
Giờ cứ thế mà áp dụng đi
 
Upvote 0
Mã:
Sub Test()
  Dim arr
  Dim idx As Long
  Dim bChk As Boolean
  arr = Sheet1.Range("E4:E1000").Value
  ReDim aRes(1 To UBound(arr), 1 To 1)
  For idx = 1 To UBound(arr)
    If arr(idx, 1) <> Empty Then
      If bChk = (arr(idx, 1) < 50) Then
        aRes(idx, 1) = arr(idx, 1)
        bChk = Not bChk
      End If
    End If
  Next
  Sheet1.Range("G4:G1000").Value = aRes
End Sub

Code trên khi chạy trên 1 sheet thì không sao, nhưng khi chạy trên nhiều sheet 1 lúc, thì bị tình trạng:
- Giá trị: bChk - cuối cùng của sheet1 tính sang cho sheet2 ( khi sang sheet2 phải reset lại biến bChr) => giá trị đầu tiên lấy bị sai ( lúc >50, lúc < 50)
- Em mò mãi mới thấy cách sửa đc lỗi này bằng cách thêm bChk = false để reset. và thấy khi chạy nhiều sheet kết quả vẫn đúng.
-Em muốn hỏi: đó có phải là cách reset biến Bolean không và cách đúng nhất là gì ạ!
Em cảm ơn Thầy cùng các anh!
Với code trên, bạn làm cách nào chạy trên nhiều sheet 1 lúc?

. Vậy biển quảng cáo và hàng bán khác nhau.
Tùy gia chủ vậy.
Trường hợp này ta chỉ cần 1 mảng để làm việc, vừa vào vừa ra.
(vì không còn yếu tố dòng lẻ >= 50, dòng chẵn <50 cho nên bắt buộc phải giữ biến lính canh)
 
Upvote 0
Trường hợp này ta chỉ cần 1 mảng để làm việc, vừa vào vừa ra.
(vì không còn yếu tố dòng lẻ >= 50, dòng chẵn <50 cho nên bắt buộc phải giữ biến lính canh)
Bớt được một biến mảng ạ. :)
PHP:
Sub vidu2()
    Const N As Long = 50
    Dim a(), s, i As Long, flag As Boolean
    a = Sheet1.Range("E1:E20").Value
    flag = True
    For i = 1 To UBound(a, 1) Step 1
        s = a(i, 1)
        If ((Len(s) > 0) * IsNumeric(s)) = 1 Then
            If (s >= N) = flag Then
                flag = Not flag
            Else
                a(i, 1) = ""
            End If
        End If
    Next i
    Sheet1.Range("G1").Resize(UBound(a, 1), 1) = a
End Sub
 
Upvote 0
Bớt được một biến mảng ạ. :)
PHP:
Sub vidu2()
    Const N As Long = 50
    Dim a(), s, i As Long, flag As Boolean
    a = Sheet1.Range("E1:E20").Value
    flag = True
    For i = 1 To UBound(a, 1) Step 1
        s = a(i, 1)
        If ((Len(s) > 0) * IsNumeric(s)) = 1 Then
            If (s >= N) = flag Then
                flag = Not flag
            Else
                a(i, 1) = ""
            End If
        End If
    Next i
    Sheet1.Range("G1").Resize(UBound(a, 1), 1) = a
End Sub
Trường hợp thay gì lấy 3 phần tử trong 100 thì code này lại lấy tất cả rồi xóa 97 phần tử
???!!!
 
Upvote 0
Nhưng bù lại khoản chiếm bộ nhớ của RAM - trường hợp mảng có kích thước lớn).
Cái này thì tôi hơi... nghi. Cảm tính cho thấy rằng dù "dựng" 1 mảng 100 phần tử hay gán range 100 cells vào mảng thì.. cũng thế thôi. Sao lại có chuyện chiếm Ram nhiều hay ít
Bạn cho 1 ví dụ thử xem
 
Upvote 0
Cái này thì tôi hơi... nghi. Cảm tính cho thấy rằng dù "dựng" 1 mảng 100 phần tử hay gán range 100 cells vào mảng thì.. cũng thế thôi. Sao lại có chuyện chiếm Ram nhiều hay ít
Bạn cho 1 ví dụ thử xem
Mới có bài hôm trước nói về mảng kích thước lớn thì lỗi Out of memory mà anh.
Bài này dựng một biến mảng (cho cả đầu vào và đầu ra) chiếm dung lượng RAM là x (MB).
Các bài trước dựng hai biến mảng (một cho đầu vào, một cho đầu ra) có kích thước bằng nhau => chiếm dung lượng RAM = 2*x (MB)

Anh thử từng dòng 1 và 2 xem.
PHP:
Sub viduRAM()
    Dim a(), b()
1    a = Range("A1:BZ1048576").Value2
2    ReDim b(1 To UBound(a, 1), 1 To UBound(a, 2))
End Sub
 
Upvote 0
Mới có bài hôm trước nói về mảng kích thước lớn thì lỗi Out of memory mà anh.
Bài này dựng một biến mảng (cho cả đầu vào và đầu ra) chiếm dung lượng RAM là x (MB).
Các bài trước dựng hai biến mảng (một cho đầu vào, một cho đầu ra) có kích thước bằng nhau => chiếm dung lượng RAM = 2*x (MB)
...
Đối với tôi "tiết kiệm bộ nhớ" không quan trọng lắm. Trừ phi tôi biết trước là code cần làm việc với mảng MxN với M và N khá lớn. Hoặc trường hợp viết hàm đệ quy.
Lúc tôi nói chuyện "chỉ cần 1 mảng" là dụng ý khác. Giải thuật này ngầm ý là phần đầu vào sẽ đồng dạng với phần đầu ra.
Tương tự dụng ý ở bài #6 thì ngầm ý là kết quả lớn sẽ nằm ở các dòng lẻ trong khi kết quả nhỏ sẽ nằm ở các dòng chẵn.

Chủ ý: code hiệu quả là một chuyện. Tới trình độ của bạn thì nên học nhìn xa hơn nữa - điển hình là: cái dạng kết quả sẽ ra sao? ta sẽ đọc được gì từ chúng?. Bài này là một ví dụ không hay lắm, nhưng ở đây không có mấy dịp để tôi chỉ dẫn.
 
Lần chỉnh sửa cuối:
Upvote 0
Mới có bài hôm trước nói về mảng kích thước lớn thì lỗi Out of memory mà anh.
Bài này dựng một biến mảng (cho cả đầu vào và đầu ra) chiếm dung lượng RAM là x (MB).
Các bài trước dựng hai biến mảng (một cho đầu vào, một cho đầu ra) có kích thước bằng nhau => chiếm dung lượng RAM = 2*x (MB)

Anh thử từng dòng 1 và 2 xem.
PHP:
Sub viduRAM()
    Dim a(), b()
1    a = Range("A1:BZ1048576").Value2
2    ReDim b(1 To UBound(a, 1), 1 To UBound(a, 2))
End Sub
Ngay dòng lệnh 1 đã Out of memory rồi
 
Upvote 0
Chủ ý: code hiệu quả là một chuyện. Tới trình độ của bạn thì nên học nhìn xa hơn nữa - điển hình là: cái dạng kết quả sẽ ra sao? ta sẽ đọc được gì từ chúng?. Bài này là một ví dụ không hay lắm, nhưng ở đây không có mấy dịp để tôi chỉ dẫn.
Em thấy có phần hơi trừu tượng... :rolleyes::rolleyes:
Mong có dịp anh chỉ dẫn trường hợp cụ thể.
 
Upvote 0
Em thấy có phần hơi trừu tượng... :rolleyes::rolleyes:
Mong có dịp anh chỉ dẫn trường hợp cụ thể.
Điển hình:
Vì Excel chủ yếu là bảng tính trải rộng, tức là một vùng dữ liệu diễn ra thành một mảng 2 chiều.
Do đó, các bạn ở diễn đàn này quen với phương pháp 2 mảng. Một mảng đầu vào chép lại dữ liệu của bảng; và một mảng đầu ra ghi dữ liệu đã tính toán; ở giữa có thêm một phần đếm số đầu ra; làm xong thì chép lại vào bảng tính.
Nhắc lại, vì Excel chủ yếu là bảng 2 chiều cho nên phương pháp trên rất có hiệu quả.
Tuy nhiên, cũng chính vì sự hiệu quả ấy mà lâu dần các bạn, nhất là những người học code vài năm gần đây quên mất rằng đó không phải là cách duy nhất.
 
Upvote 0
Trường hợp này ta chỉ cần 1 mảng để làm việc, vừa vào vừa ra.
(vì không còn yếu tố dòng lẻ >= 50, dòng chẵn <50 cho nên bắt buộc phải giữ biến lính canh)

Có thể dùng 1 mảng: duyệt từng phần tử đầu tiên tìm số >=50, nếu gặp số <50 thì gán = 0, gặp số đầu tiên >=50 thì giữ nguyên; tiếp tục tìm số <50 cũng tương tự, nếu gặp số >=50 thì xóa về 0, giữ lại số đầu tiên <50. (Em ý tưởng vậy thôi chứ chưa code).
 
Upvote 0
Mới có bài hôm trước nói về mảng kích thước lớn thì lỗi Out of memory mà anh.
Bài này dựng một biến mảng (cho cả đầu vào và đầu ra) chiếm dung lượng RAM là x (MB).
Các bài trước dựng hai biến mảng (một cho đầu vào, một cho đầu ra) có kích thước bằng nhau => chiếm dung lượng RAM = 2*x (MB)

Anh thử từng dòng 1 và 2 xem.
PHP:
Sub viduRAM()
    Dim a(), b()
1    a = Range("A1:BZ1048576").Value2
2    ReDim b(1 To UBound(a, 1), 1 To UBound(a, 2))
End Sub
Máy tôi yêu nên tôi test vầy:
- Mở Excel (bảng tính chưa có bất cứ dữ liệu nào) và chèn code
Mã:
Sub Test()
  Dim arr
  arr = Range("A1:Z1048576").Value
End Sub
- Mở Task Manager lên, chờ máy tính ổn định, kiểm tra Ram trên máy đang 62%
- Chạy code trên, kiểm tra thấy Ram tăng lên 82%
- Test khoảng 5 lần như thế, kết quả như nhau
- Tiếp theo đổi code khác:
Mã:
Sub Test()
  Dim arr
  ReDim arr(1 To 1048576, 1 To 26)
End Sub
- Mở Task Manager lên, chờ máy tính ổn định, kiểm tra Ram trên máy đang 62%
- Chạy code trên, kiểm tra thấy Ram tăng lên 72%
- Test khoảng 5 lần như thế, kết quả như nhau
----------------
Kết luận (riêng trên máy tôi thôi nha): Dựng 1 mảng tốn ít ram hơn so với gán range vào mảng.
Nói chung là vì thấy bạn có ý kiến nên tôi test thử xem sao thôi chứ trước giờ chẳng quan tâm vụ này. Tôi thực tế lắm, cứ thấy cái nào nhanh thì dùng
 
Upvote 0
Máy tôi yêu nên tôi test vầy:
- Mở Excel (bảng tính chưa có bất cứ dữ liệu nào) và chèn code
Mã:
Sub Test()
  Dim arr
  arr = Range("A1:Z1048576").Value
End Sub
- Mở Task Manager lên, chờ máy tính ổn định, kiểm tra Ram trên máy đang 62%
- Chạy code trên, kiểm tra thấy Ram tăng lên 82%
- Test khoảng 5 lần như thế, kết quả như nhau
- Tiếp theo đổi code khác:
Mã:
Sub Test()
  Dim arr
  ReDim arr(1 To 1048576, 1 To 26)
End Sub
- Mở Task Manager lên, chờ máy tính ổn định, kiểm tra Ram trên máy đang 62%
- Chạy code trên, kiểm tra thấy Ram tăng lên 72%
- Test khoảng 5 lần như thế, kết quả như nhau
----------------
Kết luận (riêng trên máy tôi thôi nha): Dựng 1 mảng tốn ít ram hơn so với gán range vào mảng.
Nói chung là vì thấy bạn có ý kiến nên tôi test thử xem sao thôi chứ trước giờ chẳng quan tâm vụ này. Tôi thực tế lắm, cứ thấy cái nào nhanh thì dùng
Hình như anh hiểu nhầm ý của em chút ạ.
Ý của em là với trường hợp mảng kích thước lớn, dung lượng Ram giới hạn, vừa đủ cho ta dùng một biến mảng thì code trường hợp dùng một mảng dùng được, còn code dùng hai mảng (một mảng chứa đầu vào, một mảng chứa kết quả đầu ra) thì không dùng được.
Còn so sánh trường hợp mảng a copy range vào (cho dù range đều rỗng) và mảng b ta dựng (có kích thước bằng mảng a) thì a chiếm dung lượng Ram nhiều hơn b. Chắc do a còn động tác copy nữa, chi tiết chắc chờ anh nào đó vào giải thích cụ thể ạ. Hình như trước đây, có bài nói về kích thước mảng này rồi, từ bài anh @kieu manh hỏi...
 
Upvote 0
Hình như anh hiểu nhầm ý của em chút ạ.
Ý của em là với trường hợp mảng kích thước lớn, dung lượng Ram giới hạn, vừa đủ cho ta dùng một biến mảng thì code trường hợp dùng một mảng dùng được, còn code dùng hai mảng (một mảng chứa đầu vào, một mảng chứa kết quả đầu ra) thì không dùng được.
Còn so sánh trường hợp mảng a copy range vào (cho dù range đều rỗng) và mảng b ta dựng (có kích thước bằng mảng a) thì a chiếm dung lượng Ram nhiều hơn b. Chắc do a còn động tác copy nữa, chi tiết chắc chờ anh nào đó vào giải thích cụ thể ạ. Hình như trước đây, có bài nói về kích thước mảng này rồi, từ bài anh @kieu manh hỏi...
Nói thật là trước giờ tôi cũng chưa từng làm việc với mảng quá lớn trên Excel. Quan điểm của tôi là: Nếu như có dữ liệu khủng như vậy thì ta phải tính đến việc thay đổi hệ quản trị CSDL chứ sao lại làm trên Excel
Ngoài ra (cũng là quan điểm cá nhân): Chẳng việc gì phải tiết kiệm 1 biến để đi dùng chung như thế. Cái nào ra cái đó để kiểm soát cho dễ
 
Upvote 0
...
Còn so sánh trường hợp mảng a copy range vào (cho dù range đều rỗng) và mảng b ta dựng (có kích thước bằng mảng a) thì a chiếm dung lượng Ram nhiều hơn b. Chắc do a còn động tác copy nữa, chi tiết chắc chờ anh nào đó vào giải thích cụ thể ạ. Hình như trước đây, có bài nói về kích thước mảng này rồi, từ bài anh @kieu manh hỏi...
So sánh khập khễnh.
Mảng ở đây là dạng variant.
Một trường hợp thì do copy từ range ra cho nên mỗi phần tử đều đã xác định (empty thì cũng là xác định - dù nhỏ hơn có dữ liệu 1 chút)
Trường hợp kia thì chỉ mới có chỗ cho mỗi phần tử. Chúng còn chưa có chỗ để chỉ vào.
Sau khi gán được từng ô trong bảng tính cho mảng rồi hãy tính đến chuyện so sánh.

Chú: tôi đã nói với bạn về cái nhìn ở một thớt khác rồi. Bạn đặt vấn đề tiết kiệm này nọ thì chỉ là vấn đề của hiện tại (chuyện trước mắt). Muốn nói chuyện về tương lai (chuyện kế tiếp) bạn phải biết nhìn kết quả (xem lại bài #29)
Giải quyết tốt vấn đề hiện tại chỉ đưa bạn đến trình độ chuyên nghiệp (cái địa vị mà nhiều người gọi là pro). Phải nhìn được tổng thể và xa hơn nữa mới có hy vọng tiến lên hàng thượng sư (cái địa vị mà tôi vẫn gọi là guru)
 
Lần chỉnh sửa cuối:
Upvote 0
Bổ sung:
Cái vụ đếm bộ nhớ thì có (ít nhất) 1 người ở đây biết rất rõ. Vì anh ta (theo tôi nghĩ) có sở thích và khả năng tìm đến nơi đến chốn.
Tôi nhớ có một bài anh ta giải thích cặn kẽ về cách sử dụng bộ nhớ của loại biến variant, lần khác giải thích cặn kẽ về kỹ thuật truy cứu bộ nhớ của mảng (theo cột hay theo dòng)
Hình như mấy bữa nay anh ta đi vắng.
 
Upvote 0
Bổ sung:
Cái vụ đếm bộ nhớ thì có (ít nhất) 1 người ở đây biết rất rõ. Vì anh ta (theo tôi nghĩ) có sở thích và khả năng tìm đến nơi đến chốn.
Tôi nhớ có một bài anh ta giải thích cặn kẽ về cách sử dụng bộ nhớ của loại biến variant, lần khác giải thích cặn kẽ về kỹ thuật truy cứu bộ nhớ của mảng (theo cột hay theo dòng)
Hình như mấy bữa nay anh ta đi vắng.
Bác đang nói bác @batman1 phải không? Ngoài ra, bác @nguyen Duy Tuân cũng thế, bác Tuân có bài viết tăng tốc copy mảng bằng api CopyMemory trong diễn đàn.
Khi khởi tạo mảng variant thì vùng nhớ cho các phần tử mảng =16bytes x số phần tử, khi gán nội dung của range trống vào cũng thế do nội dung phần tử mảng là null nằm hoàn toàn trong variant. Ở đây bộ nhớ tốn nhiều hơn do thao tác copy range vào mảng chứ không phải mảng phình to ra.
 
Upvote 0
.... Ở đây bộ nhớ tốn nhiều hơn do thao tác copy range vào mảng chứ không phải mảng phình to ra.
Tôi dự định đề nghị phân tích page faults để xem có gì đăc biệt. Nhưng có bằng chứng này thì thôi khong cần. Vì như vậy đủ để chứng tỏ phương pháp so sánh trên hoàn toàn khập khễnh đến què quặt.
... Ngoài ra, bác @nguyen Duy Tuân cũng thế, bác Tuân có bài viết tăng tốc copy mảng bằng api CopyMemory trong diễn đàn....
Ngày xưa, MS dùng C/C++ để thực hiện các hàm Excel và một số API.
MemCopy và MemMove là hai Macro (macro máy chứ khong phải của Excel) nổi tiếng là nhanh của C/C++
Lưu ý rằng tôi dùng từ "ngày xưa" ở trên. Hiện nay, với kỹ thuật cải tiến của compiler (trình dịch), hầu hết các nên tảng đều có ngôn ngữ viết riêng của họ. Rất có thể MS đã có trình dịch và ngôn ngữ nào đó để viết các macro cho API's
 
Upvote 0
Tôi dự định đề nghị phân tích page faults để xem có gì đăc biệt. Nhưng có bằng chứng này thì thôi khong cần. Vì như vậy đủ để chứng tỏ phương pháp so sánh trên hoàn toàn khập khễnh đến què quặt.

Ngày xưa, MS dùng C/C++ để thực hiện các hàm Excel và một số API.
MemCopy và MemMove là hai Macro (macro máy chứ khong phải của Excel) nổi tiếng là nhanh của C/C++
Lưu ý rằng tôi dùng từ "ngày xưa" ở trên. Hiện nay, với kỹ thuật cải tiến của compiler (trình dịch), hầu hết các nên tảng đều có ngôn ngữ viết riêng của họ. Rất có thể MS đã có trình dịch và ngôn ngữ nào đó để viết các macro cho API's
Đoạn trên là suy đoán của em chứ không phải bằng chứng đâu.
Các hàm win api nếu MS dùng ngôn ngữ và trình dịch khác C/C++ có lẽ mọi người ít nhiều đã nghe thông tin về nó chứ khó giữ bí mật lắm vì bí mật quá thì ít người tham gia phát triển được. Những hàm đơn giản thì có thể dùng Assembly.
 
Upvote 0
....
Các hàm win api nếu MS dùng ngôn ngữ và trình dịch khác C/C++ có lẽ mọi người ít nhiều đã nghe thông tin về nó chứ khó giữ bí mật lắm vì bí mật quá thì ít người tham gia phát triển được. Những hàm đơn giản thì có thể dùng Assembly.
Thời buổi bi giờ kiến thức và kỹ thuật trình dịch cao lắm. Người ta tự chế ra trình dịch chuyên cho mình là chuyện thường.
Điển hình: Lịch sử của C bắt đầu từ B. B là ngôn ngữ được tác giả tự chế để viết hệ thống vận hành Unix cho máy PDP11.
Một ngon ngữ nổi tiếng khác là PHP cũng có nguồn gốc rất hai lúa.

Chú về assembly: tuỳ theo cách gọi. Thường thì những nhóm lệnh assembly được gộp lại thành những khối gọi là Macro. (vì vậy tôi mới nói các hàm MemCopy và MemMove của C được thực hiện, tức là khởi đầu và bảo trì, bằng Macro)
 
Upvote 0

Bài viết mới nhất

Back
Top Bottom