"Đặt" dữ liệu nhị phân trên sheet

Liên hệ QC

siwtom

Thành viên gắn bó
Tham gia
19/3/08
Bài viết
2,127
Được thích
4,209
Tôi muốn làm một việc nhưng sợ rằng mình đang "đập cửa đang mở" nên hỏi cho chắc chắn.
Tôi muốn "đặt" dữ liệu nhị phân lên sheet. Trong kho tàng GPE đã có ai hướng dẫn cách "đặt" chưa? Tôi có một ý tưởng nhưng rất có thể đã có "thuật toán" rồi.
Vd. tôi có một video clip ngắn, một đoạn nhạc ngắn, và tôi muốn "đặt" nội dung của chúng trên sheet. Khi cần thì dữ liệu được lấy từ sheet và nạp vào RAM rồi play từ RAM hoặc nếu cần thì bung ra đĩa cứng rồi play. "Đặt" trên sheet để khỏi phải đính kèm nhạc, phim với tập tin Excel, và thay vì 2 tập tin thì chỉ có 1 mà thôi.
Đã có ai làm cái việc "đặt" kia chưa các bạn? Cũng cần nói rõ là tôi chỉ hỏi về ý tưởng, hướng đi, còn về viết code thì tôi có thể tự làm.
 
Ý tưởng này theo tôi biết thì GPE chưa ai làm (mã nhị phân).

Trước kia có 1 file cũa Nguyễn Duy Tuân soạn nhạc hoặc ghi nhạc trên Excel rồi play dạng midi (nhiều loại nhạc cụ). Nhưng không phải ghi mã nhị phân mà ghi ký hiệu tượng trưng nốt nhạc.
Tôi cũng có 1 file ghi lại các nước đi của 1 trận cờ tướng sau đó tái hiện lại, nhưng cũng không phải ghi mã nhị phân mà là ghi mã vị trí trên bàn cờ.

Vậy bạn yên tâm làm cho anh em học hỏi.
 
Ý tưởng này theo tôi biết thì GPE chưa ai làm (mã nhị phân).

Trước kia có 1 file cũa Nguyễn Duy Tuân soạn nhạc hoặc ghi nhạc trên Excel rồi play dạng midi (nhiều loại nhạc cụ). Nhưng không phải ghi mã nhị phân mà ghi ký hiệu tượng trưng nốt nhạc.
Tôi cũng có 1 file ghi lại các nước đi của 1 trận cờ tướng sau đó tái hiện lại, nhưng cũng không phải ghi mã nhị phân mà là ghi mã vị trí trên bàn cờ.

Vậy bạn yên tâm làm cho anh em học hỏi.

Thế thì tôi viết cụ thể, biết đâu có ai nhớ lại là đã có người làm rồi.
Tôi có một mảng bai. Tôi dự định sẽ ghi trên sheet dưới dạng bitmap.
Cụ thể là nếu tôi có mảng 3000000 bai (3 MB) thì trên sheet sau khi thao tác sẽ có ảnh (Image) khoảng 1000 x 1000 pixels. Khi cần thì từ ảnh này lại lấy ra 3000000 bai kia.
 
Tôi muốn làm một việc nhưng sợ rằng mình đang "đập cửa đang mở" nên hỏi cho chắc chắn.
Tôi muốn "đặt" dữ liệu nhị phân lên sheet. Trong kho tàng GPE đã có ai hướng dẫn cách "đặt" chưa? Tôi có một ý tưởng nhưng rất có thể đã có "thuật toán" rồi.
Vd. tôi có một video clip ngắn, một đoạn nhạc ngắn, và tôi muốn "đặt" nội dung của chúng trên sheet. Khi cần thì dữ liệu được lấy từ sheet và nạp vào RAM rồi play từ RAM hoặc nếu cần thì bung ra đĩa cứng rồi play. "Đặt" trên sheet để khỏi phải đính kèm nhạc, phim với tập tin Excel, và thay vì 2 tập tin thì chỉ có 1 mà thôi.
Đã có ai làm cái việc "đặt" kia chưa các bạn? Cũng cần nói rõ là tôi chỉ hỏi về ý tưởng, hướng đi, còn về viết code thì tôi có thể tự làm.

Ý tưởng này cũng hay, có điều là trong Excel 2003 trở về trước, số ký tự lưu trong 1 cell là 256 ký tự, Excel 2007 trở lại đây là 32,768 ký tự. Nếu với định dạng Excel2007 mà lưu mỗi cell một byte thì có thể lưu 17,179,869,184 byte (16,384 MB). Không biết anh sẽ tổ chức việc lưu trên sheet như thế nào? Dung lượng file nhị phân có lẽ cũng giới hạn?
 
Ý tưởng này cũng hay, có điều là trong Excel 2003 trở về trước, số ký tự lưu trong 1 cell là 256 ký tự, Excel 2007 trở lại đây là 32,768 ký tự. Nếu với định dạng Excel2007 mà lưu mỗi cell một byte thì có thể lưu 17,179,869,184 byte (16,384 MB). Không biết anh sẽ tổ chức việc lưu trên sheet như thế nào? Dung lượng file nhị phân có lẽ cũng giới hạn?

Tôi ghi mảng bai với "tư cách" là mảng bai định nghĩa mầu của các pixels trong tập tin BMP 24bit. Tức tạo BMP có mảng bai cho trước là mảng bai mầu. BMP sau đó được nạp vào Image trên sheet. Cũng có thể không cần tạo BMP trên đĩa nhưng có thể có người cần, và BMP luôn có thể xóa nếu không thích.
-------------
Tải về tại:

http://www.mediafire.com/?numsilmpvkx72l3

Tôi vừa viết xong code. Chú thích đầy đủ. Nếu ai muốn hiểu chút về code và "thuật toán" thì tôi sẽ giải thích ngắn gọn. Trước tiên ta nói về cấu trúc tập tin BMP.
Ở đầu mỗi BMP là 1 cấu trúc BITMAPFILEHEADER (tổng cộng 14 bai) có chứa những thông tin về tập tin, trong đó có trường bfOffBits (Long). Tiếp theo là cấu trúc BITMAPINFOHEADER (40 bai) chứa các thông tin về bitmap: width, height, bao nhiêu bit v...v. Trong trường hợp bitmap 1bit, 4bit, 8bit thì tiếp theo là palette (bảng mầu) được ghi. Phần này có độ lớn thay đổi. Vd. nếu là bitmap 8bit thì nó có bảng mầu 2^8 = 256 mầu, mà mỗi mầu được xác định bằng 3 bai (3 thành phần Red, Green, Blue) - vậy palette chiếm 768 bai.
Tôi chọn bitmap 24bit vì nó đơn giản. Với bitmap 24bit thì sau cấu trúc BITMAPINFOHEADER không có bảng mầu (do bitmap không dùng bảng mầu). Trường bfOffBits trong cấu trúc BITMAPFILEHEADER chứa offset (tính từ đầu tập tin) tới một mảng bai, tôi tạm gọi là mảng M. Mảng M có ý nghĩa khác nhau tùy bitmap là 1, 4, 8, 16, 24 hay 32bit.
Ví dụ với bitmap 8bit thì mảng M này chứa những bai là chỉ số tới bảng mầu (palette). Chẳng hạn với pixel ở dòng y cột x ta có bai tương ứng trong mảng M có giá trị 5 thì có nghĩa là nhẩy tới mầu thứ 5 (tính từ 0 do bai = 0..255) trong palette ta sẽ đọc được 3 thành phần R, G, B của mầu pixel ở dòng y cột x.
Bitmap 24bit không có palette, và mảng M chính là mảng bai định nghĩa 3 thành phần R, G, B của mỗi pixel.
Ở trên tôi viết: "pixel ở dòng y cột x ta có bai tương ứng trong mảng M". Tương ứng ở đây là gì?
Là các dòng pixels được ghi nối tiếp nhau từ dòng "cuối" tới dòng "đầu" (hoặc từ dòng đầu tới dòng cuối).
Với bitmap 24bit mỗi dòng pixels được ghi trong mảng M như sau: 3 bai B, G, R (theo thứ tự đó) của pixel thứ nhất, 3 bai B, G, R của pixel thứ 2, ..., 3 bai B, G, R của pixel cuối cùng trong dòng. Tổng cộng mỗi dòng dùng hết 3*width bai. Nếu 3*width không là bội của 4 thì trong tập tin BMP mỗi dòng được ghi thêm từ 1 tới 3 bai 0 để số bai trong dòng là bội của 4. Tổng cộng có height dòng như thế được ghi nối tiếp nhau. Biết pixel ở dòng cột nào thì cũng tính được vị trí 3 bai trong mảng M mà xác định B, G, R của pixel đó.
Từ miêu tả trên thì nảy ra ý tưởng ghi mảng bai tùy ý. Tức là ta tạo một BMP nào đó mà nó có một đoạn bai liên tục "trùng" với mảng bai cần ghi. Để về sau dễ đọc ra thì ta tạo BMP mà mảng M của nó ở đoạn đầu có chứa mảng bai cần ghi. Hơn thế nữa do mảng cần ghi và mảng M có thể có độ lớn khác nhau (mảng cần ghi có thể có độ lớn không là bội của 4 còn mảng M phải có độ lớn là bội của 4) nên để về sau có được mảng M thì biết đọc ra bao nhiêu bai cho mảng đã ghi thì ta làm như sau: Ta cần ghi mảng Arr có x bai. Ta tạo mảng tmp có độ lớn (x + 4) bai. Trong 4 bai đầu của tmp ta ghi độ lớn của Arr, tức giá trị x (Long), tiếp theo ta ghi toàn bộ các bai của mảng Arr. Và ta tạo BMP sao cho mảng M của nó có đoạn đầu "trùng" với mảng tmp. Khi cần đọc lại mảng đã ghi thì chỉ cần có mảng M rồi ta đọc 4 bai đầu để biết cần đọc ra bao nhiêu bai rồi tiếp theo đọc bấy nhiêu bai ra.
Từ miêu tả cấu trúc bitmap 24bit thì ta thấy là việc đọc mảng M không có gì khó khăn. Offset của nó được ghi trong trường bfOffBits trong cấu trúc BITMAPFILEHEADER. Nhưng trong code tôi dùng hàm của system để đọc ra mảng M - hàm GetDIBits.
------------
Trong tập tin đính kèm có 2 ví dụ.
1. Nhấn nút "Test 1": tạo mảng Arr chứa 100 giá trị từ 1 tới 100 --> tạo BMP có mảng M chứa mảng Arr --> BMP được ghi trong thư mục của tập tin XLS --> đồng thời cũng tạo Image trên sheet rồi nap BMP vào Image. Sau đó từ tập tin BMP trên đĩa đọc ra mảng đã ghi Arr1, và từ Image trên sheet đọc ra mảng đã ghi Arr2, và nhập chúng vào cột A và B. Ta thấy rằng Arr1, Arr2 và mảng ban đầu là y hệt nhau.

2. Trong ví dụ 2 tôi đã nhập sẵn nội dung của video clip. Nhấn nút "Play video clip" thì mảng bai sẽ được lấy ra từ Image trên sheet rồi ghi mảng bai đó trong thư mục của tập tin XLS với tên "CafeSuaNong.wmv". Đồng thời BMP từ Image trên sheet được ghi ra đĩa trong thư mục của tập tin XLS với tên "CafeSuaNong.bmp". Tiếp theo video clip "CafeSuaNong.wmv" được chiếu. Tôi dùng hàm đơn giản tự tạo trong module đính kèm - mciSendString - để chiếu. Nhấn nút "Close video" sẽ dừng và đóng device.
--------------
Tôi có câu hỏi các bạn: Tại sao tập tin XLS lại phình to lên tới 12,5 MB? Các tập tin tôi tách ra và ghi trên đĩa thì BMP có 4,17 MB (4.381.434 bai), WMV có 4,17 MB (4.379.842 bai).
Tất nhiên tôi biết nó có cái gì mà to thế. Tôi ghi lại ở dạng XLSM rồi dùng WinRar bung ra thì thấy trong thư mục xl\media có tập tin image1.emf - có 97 x 97 pixels mà độ lớn 8,35 MB. Thư mục xl\activeX có activeX1.bin với 4,17 MB. Đúng là khó hiểu thật.
-------------
Code có ghi chú đầy đủ. Nếu không xem được thì trong VBE: Tools --> Options --> thẻ Editor Format, mục Font --> chọn Times New Roman (vietnamese)
 

Quên không giới thiệu các hàm trong module:

1. Khi ta đã có "từ đâu đó" mảng bai Arr thì ta gọi Sub ArrayBytesToBitmapFile và truyền Arr cùng với đường dẫn đầy đủ tới tập tin BMP. Sub sẽ tạo ra BMP có chứa các bai của Arr và ghi trên đĩa với đường dẫn mà bạn nhập. Nếu bạn truyền cả tên Image thì Image với tên như thế sẽ được tạo trên ActiveSheet rồi nap BMP vào nó.

2. Nếu bạn muốn ghi toàn bộ một tập tin bất kỳ thì gọi Sub FileToBitmapFile và truyền tên đầy đủ của tập tin cần ghi đó, tên đầy đủ của tập tin BMP. Sub sẽ tạo ra BMP có chứa các bai của tập tin cần ghi và ghi trên đĩa với đường dẫn mà bạn nhập. Nếu bạn truyền cả tên Image thì Image với tên như thế sẽ được tạo trên ActiveSheet rồi nap BMP vào nó.

3. Nếu trước đó bạn ghi mảng bai trong BMP nạp vào Image trên sheet và bây giờ bạn muốn lấy lại mảng bai này thì gọi hàm ArrayBytesFromImage và truyền sheet cũng như tên Image có trên sheet đó. Hàm trả về mảng bai đã ghi trước đó

4. Nếu trước đó bạn ghi mảng bai trong tập tin BMP trên đĩa và bây giờ bạn muốn lấy lại mảng bai này thì gọi hàm ArrayBytesFromBitmapFile và tên đầy đủ của tập tin BMP. Hàm trả về mảng bai đã ghi trước đó
 
Web KT

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

Back
Top Bottom