【问题标题】:How to get the checkbox value selected from excel sheet如何获取从excel表中选择的复选框值
【发布时间】:2018-08-02 23:33:36
【问题描述】:

我正在处理一项与使用 Java 读取包含单选按钮和复选框的 excel 相关的任务,当我尝试读取包含复选框的单元格的数据时,我已经尝试了很多但无法继续前进正在返回一个空值。

有人可以帮忙吗?

【问题讨论】:

    标签: java apache-poi


    【解决方案1】:

    控件不包含在单元格中,而是作为形状悬停在图纸上的绘图层中,并且仅锚定到单元格。因此单元格可能为空(因为其中没有内容),尽管形状悬停在其上方并固定在其上。

    此外,还有两种不同的控制方式。有表单控件和ActiveX 控件。 ActiveX 控件的状态存储在二进制代码部分 activeX1.bin 中,因此获取它们的状态非常困难。

    在早期的Excel 版本(例如2007)中,所有控件的锚点信息仅存储在/xl/drawings/vmlDrawing1.vml 中。更高版本将它们存储在默认绘图中和

    <controls>
     <mc:AlternateContent>
      ...
     </mc:AlternateContent>
    </controls>
    

    表中的部分XML 也是。幸运的是,还有 /xl/drawings/vmlDrawing1.vml 用于向后兼容。

    以下代码会解析/xl/drawings/vmlDrawing1.vml 以获取可能锚定到单元格的控件。如果找到,它会得到这个控件,如果这个控件是一个表单控件并且不是一个ActiveX 控件,那么它也可以获得它的状态。对于ActiveX 控件,它只获取信息,即“Pict”锚定到此单元格。

    Excel:

    代码:

    import java.io.*;
    
    import org.apache.poi.ss.usermodel.*;
    import org.apache.poi.xssf.usermodel.*;
    
    import org.apache.poi.POIXMLDocumentPart;
    
    import org.apache.poi.util.Units;
    
    import org.apache.xmlbeans.XmlCursor;
    import org.apache.xmlbeans.XmlObject;
    
    import javax.xml.namespace.QName;
    
    class ReadExcelXSSFControls {
    
     public ReadExcelXSSFControls() throws Exception {
      XSSFWorkbook wb  = (XSSFWorkbook)WorkbookFactory.create(new FileInputStream("ExcelWithControls.xlsx"));
    
      Sheet sheet = wb.getSheetAt(0);
      for (Row row : sheet) {
       for (int c = 0; c < 2; c++) {
        Cell cell = row.getCell(c);
        if (row.getRowNum() == 0) {
         System.out.print(cell + "\t");
        } else {
         if (c == 0) {
          System.out.print(cell + "\t");
         } else if (c == 1) {
          if (cell == null) cell = row.createCell(c);
          Control contol = getControlAt((XSSFCell)cell);
          System.out.print(contol);     
         }
        }
       }
       System.out.println();
      }
    
      wb.close();
     }
    
     private Control getControlAt(XSSFCell cell) throws Exception {
      XSSFSheet sheet = cell.getSheet();
      Row row =  cell.getRow();
      int r = row.getRowNum();
      int c = cell.getColumnIndex();
    
      int drheight = (int)Math.round(sheet.getDefaultRowHeightInPoints() * Units.PIXEL_DPI / Units.POINT_DPI);
      int rheight = (int)Math.round(row.getHeightInPoints() * Units.PIXEL_DPI / Units.POINT_DPI);
      row = null;
      if(r > 0) row = sheet.getRow(r-1);
      int rheightbefore = (row!=null)?(int)Math.round(row.getHeightInPoints() * Units.PIXEL_DPI / Units.POINT_DPI):drheight;
      row = sheet.getRow(r+1);
      int rheightafter = (row!=null)?(int)Math.round(row.getHeightInPoints() * Units.PIXEL_DPI / Units.POINT_DPI):drheight;
    
      String name = null;
      String objectType = null;
      String checked = null;
    
      XmlCursor xmlcursor = null;
      if (sheet.getCTWorksheet().getLegacyDrawing() != null) {
       String legacyDrawingId = sheet.getCTWorksheet().getLegacyDrawing().getId();
       POIXMLDocumentPart part = sheet.getRelationById(legacyDrawingId);
       XmlObject xmlDrawing = XmlObject.Factory.parse(part.getPackagePart().getInputStream());
       xmlcursor = xmlDrawing.newCursor();
       QName qnameClientData = new QName("urn:schemas-microsoft-com:office:excel", "ClientData", "x");
       QName qnameAnchor = new QName("urn:schemas-microsoft-com:office:excel", "Anchor", "x");
       boolean controlFound = false;
       while (xmlcursor.hasNextToken()) {
        XmlCursor.TokenType tokentype = xmlcursor.toNextToken();
        if (tokentype.isStart()) {
         if (qnameClientData.equals(xmlcursor.getName())) {
          controlFound = true;
          XmlObject clientdata = xmlcursor.getObject();
          XmlObject[] xmlchecked = clientdata.selectPath("declare namespace x='urn:schemas-microsoft-com:office:excel' x:Checked");
          if (xmlchecked.length > 0) {
           checked = "Checked";
          } else {
           checked = "Not checked";
          }
          while (xmlcursor.hasNextToken()) {
           tokentype = xmlcursor.toNextToken(); 
           if (tokentype.isAttr()) {
            if (new QName("ObjectType").equals(xmlcursor.getName())) {
             objectType = xmlcursor.getTextValue();
             name = objectType + " in row " + (r+1);
            } 
           } else {
            break;
           }
          }
         } else if (qnameAnchor.equals(xmlcursor.getName()) && controlFound) {
          controlFound = false;
          String anchorContent = xmlcursor.getTextValue().trim();
          String[] anchorparts = anchorContent.split(",");
          int fromCol = Integer.parseInt(anchorparts[0].trim());
          int fromColDx = Integer.parseInt(anchorparts[1].trim());
          int fromRow = Integer.parseInt(anchorparts[2].trim());
          int fromRowDy = Integer.parseInt(anchorparts[3].trim());
          int toCol = Integer.parseInt(anchorparts[4].trim());
          int toColDx = Integer.parseInt(anchorparts[5].trim());
          int toRow = Integer.parseInt(anchorparts[6].trim());
          int toRowDy = Integer.parseInt(anchorparts[7].trim());
    
          if (fromCol == c /*needs only starting into the column*/
           && (fromRow == r || (fromRow == r-1 && fromRowDy > rheightbefore/2f)) 
           && (toRow == r || (toRow == r+1 && toRowDy < rheightafter/2f))) {
    //System.out.print(fromCol + ":" +fromColDx + ":" + fromRow + ":" + fromRowDy + ":" + toCol + ":" + toColDx + ":" + toRow + ":" + toRowDy);
           break;
          }
         } 
        } 
       }
      }
    
      if (xmlcursor!=null && xmlcursor.hasNextToken()) 
       return new Control(name, objectType, checked, r, c);
    
      return new Control("Not found", "unknown", "undefined", r, c); 
     }
    
     public static void main(String[] args) throws Exception {
      ReadExcelXSSFControls o = new ReadExcelXSSFControls();
     }
    
     private class Control {
      private String name;
      private String objectType;
      private String checked;
      private int row;
      private int col;
      public Control(String name, String objectType, String checked, int row, int col) {
       this.name = name;
       this.objectType = objectType;
       this.checked = checked;
       this.row = row;
       this.col= col;
      }
      public String getName() {
       return this.name;
      }
      public String getObjectType() {
       return this.objectType;
      }
      public String getChecked() {
       return this.checked;
      }
      public int getRow() {
       return this.row;
      }
      public int getCol() {
       return this.col;
      }
      public String toString() {
       return this.name + ":r/c:" +row+ "/" + col + ":" + this.checked;
      }
     }
    }
    

    结果:

    axel@arichter:~/Dokumente/JAVA/poi/poi-3.17$ java -cp .:./*:./lib/*:./ooxml-lib/* ReadExcelXSSFControls 
    Product  Status 
    a        Checkbox in row 2:r/c:1/1:Checked
    b        Not found:r/c:2/1:undefined
    c        Checkbox in row 4:r/c:3/1:Not checked
    d        Checkbox in row 5:r/c:4/1:Checked
    e        Radio in row 6:r/c:5/1:Checked
    f        Not found:r/c:6/1:undefined
    g        Not found:r/c:7/1:undefined
    e        Checkbox in row 9:r/c:8/1:Checked
    f        Not found:r/c:9/1:undefined
    h        Radio in row 11:r/c:10/1:Not checked
    ActiveX  Pict in row 14:r/c:13/1:Not checked
    

    【讨论】:

    • 嗨阿克塞尔,感谢您的代码。但是我面临一个问题。所有的复选框都被识别,但仍然对于某些复选框,未正确返回选中的值。我正在努力解决这个问题,但我们将不胜感激。
    • @Prabahar:如前所述,无法使用我的代码解析 ActiveX 控件。但是,如果您的控件是表单控件并且它不起作用,那么我怀疑这些控件不是使用Excel 创建和/或操作的,而是使用任何未正确更新/xl/drawings/vmlDrawing1.vml 的第三方软件。
    • Axel:这是文档中的错误,我已修复。现在一切正常。伟大的!!我有另一个查询,当我尝试对无法继续执行此代码使用 XLS 时。 getRelations 方法不可用。这个代码也适用于 XLS 吗?有没有其他方法可以在 XLS 中实现复选框读取?
    • @Prabahar:此代码仅适用于 XSSF(Office Open XML 文件格式,*.xlsx)。不,我不知道如何从HSSF(二进制 BIFF 文件格式,*.xls)读取表单控件。 HSSF 代表 Horrible SpreadSheet Format,这个名字是真的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-03-23
    • 1970-01-01
    • 2023-03-24
    • 2018-09-19
    • 2012-04-08
    • 1970-01-01
    相关资源
    最近更新 更多