Xử Lý Chuyển Đổi Hàng Thành Cột Trong Báo Cáo Nhập Liệu

Bối cảnh và Yêu cầu Nghiệp vụ

Trong các hệ thống quản lý dữ liệu, đôi khi các chỉ số được lưu trữ dưới dạng các trường riêng biệt trong cơ sở dữ liệu để đảm bảo cấu trúc rõ ràng. Tuy nhiên, khi hiển thị trên báo cáo hoặc cần nhập liệu, người dùng thường mong muốn thấy các cột này được chuyển đổi thành các hàng, phù hợp hơn với thói quen và quy trình làm việc. Đây chính là vấn đề chuyển đổi hàng-cột.

Bài viết này minh họa cách thực hiện chuyển đổi hàng-cột khi nhập dữ liệu vào báo cáo, đặc biệt trong một kịch bản thực tế của một tập đoàn điện lực sử dụng nền tảng báo cáo của Runqian để giải quyết các yêu cầu phức tạp về cấu trúc dữ liệu.

Xét một báo cáo nhập liệu điển hình với các yêu cầu sau:

  1. Đây là một báo cáo hàng tháng, yêu cầu hiển thị và cho phép chỉnh sửa dữ liệu về các dự án và tổ máy của một công ty cụ thể theo tháng.
  2. Thanh công cụ của báo cáo cần có hai nút chức năng: "Lưu Báo cáo" để lưu dữ liệu hiện tại, và "Khóa Báo cáo" để lưu và khóa dữ liệu, ngăn chặn chỉnh sửa thêm cho tháng đó.
  3. Cột thứ hai của báo cáo hiển thị tên dự án. Do cấu trúc hệ thống đặc biệt, mỗi tên dự án trên giao diện tương ứng với một tên trường trong cơ sở dữ liệu. Cột thứ ba và thứ tư chứa thông tin tổ máy. Mỗi tổ máy là một bản ghi trong cơ sở dữ liệu và dữ liệu được phân tán trong hai bảng: rep_tl_config và rep_tl_yb. Việc truy xuất và ghi dữ liệu phải dựa vào tên dự án để tương tác với các bảng phù hợp.

Giải pháp Thiết kế Báo cáo

Báo cáo được thiết kế với cấu trúc đơn giản như sau:

  • Cột A: Cột số thứ tự.
  • Cột B: Tên dự án.
  • Cột C: Được cấu hình là ô chiều (dimension cell). Do tên dự án ở Cột B có thể chứa ký tự đặc biệt không hoàn toàn khớp với tên trường trong cơ sở dữ liệu, Cột C dùng để lưu trữ tên trường tương ứng trong cơ sở dữ liệu, đảm bảo việc truy xuất dữ liệu chính xác.
  • Cột D, E: Ô giá trị, dùng để hiển thị dữ liệu của hai tổ máy khác nhau.
  • Cột F: Cột thông tin cố định.
  • Cột G: Cột điều khiển trạng thái khóa dữ liệu trên giao diện.

Các cột C, D, E và G cần được gán tên trường tương ứng để liên kết với các đối tượng dữ liệu được truy xuất.

Cấu hình Truy vấn Dữ liệu

Do cấu trúc dữ liệu phức tạp, việc truy vấn dữ liệu được thực hiện bằng một tập lệnh xử lý dữ liệu (DFX), sử dụng công cụ EsProc. Tập lệnh này được chia thành hai phần:

Phần 1: Lấy dữ liệu từ bảng rep_tl_config

  1. Kết nối tới nguồn dữ liệu.
  2. Lấy tên công ty từ bảng dữ liệu và gán vào biến companyName.
  3. Xác định tháng báo cáo: Nếu không có tháng được truyền vào, mặc định lấy tháng trước của thời gian hệ thống hiện tại. Ví dụ: >reportMonth = if(paramMonth == null, date(now(), "yyyy-MM").lastMonth(), date(paramMonth + "-01")).
  4. Định nghĩa các trường cần lấy từ hai bảng dữ liệu.
  5. Phân tích tham số ID nhóm tổ máy (groupId) thành groupId1 và groupId2, giả sử định dạng truyền vào là #1#2.
  6. Truy xuất dữ liệu ban đầu từ bảng rep_tl_config.
  7. Sử dụng hàm pivot của EsProc để chuyển đổi hàng-cột dữ liệu từ bước 5: các tên trường (cột) được chuyển đổi thành các giá trị trong hàng, tạo ra một cấu trúc dữ liệu mới, ví dụ: data_pivot = raw_data.pivot(projectName, groupID, valueField).
  8. Nhóm dữ liệu sau khi pivot theo mã số thiết bị khử lưu huỳnh (desulfurizationDeviceID) và lưu vào một cột data.
  9. Lấy dữ liệu cho tổ máy thứ nhất (ví dụ, data_unit1) từ nhóm dữ liệu ở bước 8.
  10. Lấy dữ liệu cho tổ máy thứ hai (ví dụ, data_unit2) từ nhóm dữ liệu ở bước 8.
  11. Ghép nối data_unit1 và data_unit2 dựa trên một trường chung như số thứ tự.
  12. Chọn các trường cần thiết, lúc này dữ liệu đã được chuyển đổi hàng-cột, với tên dự án là giá trị trong một cột và dữ liệu tương ứng của hai tổ máy ở các cột khác. Ví dụ:
    | Project      | Unit1Data | Unit2Data |
    |--------------|-----------|-----------|
    | Project A    | Value 1.1 | Value 2.1 |
    | Project B    | Value 1.2 | Value 2.2 |
    
  13. Gán đối tượng dữ liệu đã xử lý (ví dụ, từ bước 12) cho đối tượng configData.

Phần 2: Lấy dữ liệu từ bảng rep_tl_yb

  1. Truy xuất dữ liệu từ bảng rep_tl_yb.
  2. Xác định cờ khóa (isLocked): nếu dữ liệu từ rep_tl_yb trống, tức là lần đầu truy cập tháng này, cờ là false; ngược lại, lấy giá trị từ cơ sở dữ liệu.
  3. Nếu dữ liệu từ rep_tl_yb trống, bổ sung các trường companyName, reportMonth, isCorrected, và flag vào đối tượng configData đã có, trả về cho báo cáo (phần dữ liệu này sẽ trống).
  4. Nếu có dữ liệu từ rep_tl_yb, tiếp tục xử lý tương tự như phần 1 (các bước từ 8 đến 12) để lấy dữ liệu cần thiết và cập nhật vào đối tượng configData.

Cuối cùng, các trường của đối tượng configData được gán cho các ô tương ứng trên báo cáo, ví dụ: Cột C gán với configData.Project, Cột D gán với configData.Unit1, Cột E gán với configData.Unit2, và Cột G gán với configData.IsCorrected. Điều này giúp báo cáo hiển thị dữ liệu đã được truy vấn.

Cấu hình Ghi Dữ liệu

Quá trình ghi dữ liệu cũng cần được xử lý thành hai phần để ghi vào hai bảng cơ sở dữ liệu:

Phần 1: Ghi dữ liệu vào bảng rep_tl_config

  1. Lấy tên công ty từ tham số.
  2. Thiết lập giá trị cho đối tượng reportMonth, nếu tham số truyền vào trống thì lấy tháng trước của hệ thống.
  3. Định nghĩa các tên trường từ hai bảng cơ sở dữ liệu.
  4. Phân tích và gán các ID nhóm tổ máy cho groupId1 và groupId2.
  5. Tạo một đối tượng dữ liệu mới từ dữ liệu nhập liệu của báo cáo (inputData = reportData.new(Project, Unit1, Unit2, IsModified)).
  6. Lọc dữ liệu liên quan đến các trường của bảng rep_tl_config từ inputData.
  7. Chuyển đổi các hàng trở lại thành các cột bằng hàm pivot. Ví dụ:
    • Tách dữ liệu cho tổ máy 1 (gồm tên dự án và dữ liệu tổ máy 1), thêm các trường cần thiết như desulfurizationDeviceID, kksCode, company.
    • Sử dụng pivot để chuyển đổi dữ liệu tổ máy 1 từ hàng sang cột. Ví dụ: data_unit1_col = data_unit1_row.pivot(kksCode, desulfurizationDeviceID, company; ProjectName, Unit1Data).
    • Thực hiện tương tự cho tổ máy 2 để có data_unit2_col.
  8. Sử dụng hàm update@u của EsProc để thực hiện thao tác cập nhật. Dữ liệu từ data_unit1_col và data_unit2_col được nối dọc (data_unit1_col | data_unit2_col), sau đó cập nhật vào bảng rep_tl_config dựa trên các khóa như kksCode, desulfurizationDeviceID, company.

Sau các bước này, bảng rep_tl_config đã được cập nhật.

Phần 2: Ghi dữ liệu vào bảng rep_tl_yb

Quy trình tương tự như trên. Các trường từ bảng rep_tl_yb được định nghĩa, dữ liệu tương ứng từ báo cáo được trích xuất, sau đó sử dụng hàm pivot để chuyển đổi hàng thành cột và cập nhật vào bảng rep_tl_yb.

Toàn bộ quá trình truy vấn và ghi dữ liệu đã được hoàn tất.

Thiết lập Khóa Dữ liệu

Trạng thái khóa dữ liệu được điều khiển bởi trường IsCorrected (trước đó được lấy từ cơ sở dữ liệu) hiển thị ở Cột G của báo cáo. Để kiểm soát khả năng chỉnh sửa của các ô dữ liệu, thuộc tính "Biểu thức có thể chỉnh sửa" (Editable Expression) của các ô trong Cột D và E (dữ liệu hai tổ máy) được đặt là G4 != "true". Điều này đảm bảo rằng các ô chỉ có thể chỉnh sửa khi giá trị ở ô G4 không phải là "true" (tức là báo cáo chưa bị khóa).

Để thực hiện hành động khóa dữ liệu từ phía giao diện, một nút "Khóa" được thêm vào thanh công cụ của báo cáo (thường là trong tệp inputtoolbar.jsp):

<li class="borderRight submitLi" onClick="applyLock('<%=sgid %>'); return false;" href="#">
    <a title="Khóa" href="#" class="jiasuo"></a>
</li>

Khi nút này được nhấn, hàm applyLock sẽ được gọi. Hàm này được định nghĩa trong showInput.jsp như sau:

function applyLock(reportId) {
    // Duyệt qua các hàng của báo cáo (ví dụ, từ hàng 4 đến hàng 65)
    for (let rowIdx = 4; rowIdx <= 65; rowIdx++) {
        const cellId = reportId + "_G" + rowIdx;
        const cellElement = document.getElementById(cellId);
        if (cellElement) {
            cellElement.value = "true"; // Đặt giá trị của cột G thành "true"
        }
    }
    _inputSubmit(reportId); // Gọi hàm lưu báo cáo tích hợp để lưu các thay đổi
}

Chức năng JavaScript này sẽ thay đổi giá trị của cột G thành "true" cho tất cả các hàng và sau đó lưu trạng thái này vào cơ sở dữ liệu. Khi người dùng truy cập lại báo cáo cho tháng đã khóa, dữ liệu sẽ ở trạng thái không thể chỉnh sửa.

Thẻ: Dữ liệu báo cáo chuyển đổi hàng-cột báo cáo nhập liệu EsProc JavaScript

Đăng vào ngày 21 tháng 10 lúc 05:07