2011-10-10 37 views
9

Tôi đã dành nhiều giờ cố gắng xác định công thức để chuyển đổi các pixel .NET thành độ rộng cột Excel bằng định dạng OpenXML. Tôi đang sử dụng EPPlus để tạo các tài liệu xml. Tôi đang cố gắng để xác định chiều rộng cho một cột được tự động kích thước. Tôi nhận được số lượng điểm ảnh bằng cách đo chuỗi và sau đó cố gắng chuyển đổi nó thành chiều rộng cột cho OpenXML, được đo bằng ký tự mà tôi nghĩ.Công thức chuyển đổi các pixel .NET sang độ rộng Excel theo định dạng OpenXML

Tôi đã đọc tài liệu của Microsoft về cách chuyển đổi nó và cố gắng công thức họ đề nghị, nhưng nó không phải là thậm chí gần là chính xác:

http://msdn.microsoft.com/en-us/library/documentformat.openxml.spreadsheet.column.aspx

Dưới đây là mã của tôi sử dụng công thức của họ:

public double GetCharacterWidth(string Text, Font f, Graphics g) 
    { 
     float MaxDigitWidth = g.MeasureString("0", f).Width; 
     float Pixels = g.MeasureString(Text, f).Width; 

     return ((Pixels - 5)/MaxDigitWidth * 100 + 0.5)/100; 
    } 

Bất kỳ ý tưởng nào?

+0

Nếu đó là một cột được tự động kích thước tại sao không sử dụng thuộc tính phù hợp nhất như được chỉ định trong MSDN được liên kết? – PeteT

+0

Tôi đã thử rồi. Nếu bạn đặt BestFit là True và sau đó mở bảng tính, các cột không được định kích thước phù hợp. –

+0

Pixel-to-EMU là (pixel * 12700). Tôi sẽ không mong đợi độ rộng của cột là pixel. Hãy thử EMU. –

Trả lời

16

Đầu tiên chúng ta cần phải thiết lập như thế nào Excel hiện chuyển đổi (như chúng ta tự thay đổi kích thước bên trong ứng dụng Excel):

//Use 7d to promote to double, otherwise int will truncate. 
ExcelWidth = (Pixels - 12)/7d + 1;//From pixels to inches. 

Caveat: Các công thức không làm việc cho 0 (zero) Chiều rộng hoặc Pixel.
Đối với các tình huống đó, hãy sử dụng câu lệnh "if" để kiểm tra xem số không và trả về số không.

Nó cũng ném cho tôi một vòng lặp. Thay vì cố gắng tìm ra Pixels trên Width, tôi đã xem xét sự khác biệt về Pixels giữa mỗi số Width và tìm thấy nó luôn là 7. Ngoại lệ là 0 đến 1 Width; nơi có 12 pixel cho chiều rộng 1.00. Từ đó tôi đã có thể đưa ra các công thức trên, dễ dãi.

Bây giờ, những con số đó đang nắm giữ trong thế giới Excel, nhưng nếu bạn đang đặt chiều rộng cột trực tiếp trong tài liệu OpenXml thì đó là một câu chuyện hơi khác. Đây là lý do: Trong tài liệu bạn liên kết đến, hãy nói về 5 pixel:

Có 4 pixel lề lề (hai trên mỗi cạnh), cộng với 1 pixel cho đường lưới.

Bây giờ tất cả điều đó có nghĩa là Excel giả sử bạn đã tính toán trong 5 pixel này vào độ rộng bạn đang cung cấp. Khi bạn mở tài liệu của bạn trong excel và thay đổi kích thước các cột, bạn sẽ thấy rằng chiều rộng là 5 pixel ít hơn những gì bạn đặt nó vào.

Để điều chỉnh cho điều này, bạn có thể cập nhật các công thức như sau:

//Use 7d to promote to double, otherwise int will truncate. 
OpenXmlWidth = (Pixels - 12 + 5)/7d + 1;//From pixels to inches. 

này trả lời các tiêu đề của câu hỏi của bạn:
"Formula để chuyển đổi NET pixel chiều rộng Excel ở định dạng OpenXML"

Nếu bạn muốn biết cách tính chiều rộng cột xấp xỉ để tự động điều chỉnh cột dựa trên nội dung (và phông chữ) của một ô thì đó là một câu hỏi hoàn toàn khác. Các công thức được cung cấp bởi liên kết microsoft mà bạn cung cấp sẽ không hoạt động. Nhập 10 dấu chấm trong một ô và 10 cột-M trong một cột khác. Bạn sẽ thấy rằng tự động phù hợp cung cấp cho bạn 41 pixel và 129 pixel, tương ứng. Các công thức được cung cấp bởi ms không tính đến chiều rộng của các ký tự riêng lẻ. Nói cách khác; họ đã gửi cho bạn một cuộc săn đuổi ngỗng hoang dã.

Cách duy nhất để tự động điều chỉnh cột là quét qua từng hàng trong cột và tính chiều rộng của văn bản dựa trên các ký tự và phông chữ được sử dụng. Bạn sẽ sử dụng một cái gì đó giống như những gì tôi tìm thấy here. Sau đó lấy giá trị tối đa của nó và pad bằng 5. Tôi sẽ tránh phương pháp này khi xử lý bảng tính trong môi trường web vì bạn có thể xuất hàng trăm nghìn hàng với hàng chục cột - bạn sẽ có ý tưởng. Cách tiếp cận tốt nhất là đặt chiều rộng đoán tốt nhất cho các cột của bạn và đào tạo người dùng của bạn về cách tự động điều chỉnh từ excel.

Trân trọng,
"The Man Common"


Sửa - 2011/10/26:

Bởi vì tôi cảm thấy hào phóng, đây là một ví dụ về cách để có được một xấp xỉ chiều rộng cho cột của bạn. Tôi muốn tránh làm điều này cho tất cả các hàng trong một cột, vì vậy chúng ta hãy chỉ căn cứ chiều rộng của chúng ta (theo mặc định) trên giá trị trong ô tiêu đề của bạn. Dưới đây là cách bạn có thể làm điều này bằng cách sử dụng ví dụ tôi đã liên kết đến trước đó. Lưu ý: Đây là những xấp xỉ, nhưng đủ gần.

using System.Drawing; 
using System.Windows.Forms;//Add Reference. Test on webserver first. 
Font font = new Font("Calibri", 11.0f, FontStyle.Regular); 
string header = "Hello There World!"; 
int pxBaseline = TextRenderer.MeasureText("__", font).Width; 
int pxHeader = TextRenderer.MeasureText("_" + header + "_"), font).Width; 
int pxColumnWidth = pxHeader - pxBaseline + 5;//Pad with 5 for Excel. 

Caveat: Nếu bạn sử dụng mã này trong cùng một vị trí bạn đang sử dụng OpenXML, sau đó bạn có thể cần phải loại bỏ các "sử dụng" cho System.Drawing và hoàn toàn đủ điều kiện "Font" và "FontStyle" như System.Drawing.Font và System.Drawing.FontStyle. Nếu không trình biên dịch của bạn có thể nhầm lẫn các lớp này thuộc về DocumentFormat.OpenXml.Spreadsheet.

+0

Tôi đã tìm thấy công thức đầu tiên mà bạn đề xuất là chính xác nhất, mặc dù vẫn chưa đủ chính xác. Tôi phải sửa đổi nó một chút để thực hiện một "đoán tốt nhất" như bạn đã nói. –

+0

Bạn có thấy mã tôi đã đăng ở dưới cùng trong phần chỉnh sửa của mình không? Tôi sử dụng nó và nó hoạt động hoàn hảo cho nhu cầu của tôi (đưa ra hoặc lấy một vài điểm ảnh nhưng không đủ để hiển thị dấu thăng hoặc văn bản clip). Tôi có thể sẽ sửa đổi mã của tôi để quét tiêu đề và 20 hàng đầu tiên cho chiều rộng tối đa (vì đó là những gì người dùng sẽ nhìn thấy lần đầu tiên khi mở tài liệu lần đầu tiên). Đối với công thức đầu tiên, nó hoàn toàn chính xác trong việc tính toán Pixels thành OpenXML-Width để tạo ra cùng số lượng pixel chính xác khi mở tài liệu Excel (nhớ đặt cùng tên của chữ, chữ in đậm và kích cỡ). Cảm ơn các điểm! – MikeTeeVee

Các vấn đề liên quan