Is it possible to create an Excel checkbox using Apache Poi? - excel

Someone asked this question: How do I create form controls (radio, checkbox, buttons, etc.) in Excel using Apache POI (Java)? before but no answers yet.
Also is it possible to make certain rows read only?

No not as far as i know, but you can create an Excel file with checkboxes that you can read back into Java using POI in this fashion:
Create an Excel file and save as template.xlsm (so with macro's).
Insert VBA macro in the Excel file (use 'Developer' tab) and save + close the file:
Sub addCheckBoxes()
Dim i As Integer
Dim cel As Range
i = 2
For Each cel In Sheets("Sheet1").Range("A" & 3 & ":A" & 1000)
i = i + 1
If Cells(i, "B").Value <> "" Then
cel.Value = 0
With ActiveSheet.OLEObjects.Add(ClassType:="Forms.CheckBox.1", Left:=cel.Left, Top:=cel.Top, Width:=cel.Width, Height:=cel.Height)
.LinkedCell = "Sheet1!$A$" & i
.Object.Caption = "<-use"
End With
End If
Next
End Sub
Let POI read this excel file as a new Workbook:
Workbook wb = WorkbookFactory.create(new File("path to your file/template.xlsm"));
Write all your data to the file (keep Column A empty for this example !). In this example we will add a checkbox to all cells in column 'A' that have a value/text in column 'B'. It checks every row from row 3 till 1000.
Write the Workbook to file:
FileOutputStream out = new FileOutputStream("path to your file/file_with_checkboxes.xlsm");
Create a file: start_excel_file.vbs add add the code as text:
Set objExcel = CreateObject("Excel.Application")
Set objWorkbook = objExcel.Workbooks.Open("path to your file/file_with_checkboxes.xlsm")
objExcel.Application.Visible = True
objExcel.Application.Run "file_with_checkboxes.xlsm!addCheckBoxes"
Use Java to open the file through the command line by running this file: start_excel_file.vbs
The code in the start_excel_file.vbs file will open the excel file and at start up it will create the checkboxes using the addCheckBoxes() Macro. (Macro's must be enabled !)
In this code i created a boolean text that is not visible in the Excel file but will be set to TRUE if selected and FALSE is unselected afterwards. If you read the file with POI back into Java it will ignore the checkboxes but is able to read the boolean text so in Java you know what was/is the setting. (empty or FALSE = false / TRUE is true)
hope this helps and good luck =^)

Related

Extract checkbook value from a closed spreadsheet using Excel VBA

I have a fairly larger number of excel workbooks in a folder. Each workbook has one tab - Sheet1. Sheet1 includes three checkboxs: Checkbox 6, Checkbox 7 and Checkbox 8 in addition to some values in cells. I'm using this code:
Link to Code Used
to extract the cell values, but was hoping it would also be possible to determine the value (status checked or not checked) of each of the checkboxes. Is this possible? Note - None of the checkbox are linked to a particular cell.
There is no way to read anything from a closed file. Even the code you are linking to cannot do this. You will always need a program that opens the file, read the data from it, find the information you want and close it again.
For Excel files you usually use Excel, but it could be something else - I know that Python has an library to read & write Excel files (and there are more), but all of them have to open the file. Open means ask the operating system to read the data from disk, maybe set a lock, maybe later write it back, those kind of things.
That said, what you probably want is to access the data (in your case checkbox settings) without the sheet being visible. You can do so by set Application.ScreenUpdating = False, open the file, read the checkbox values, close the file and reset Application.ScreenUpdating = True. The user will not see anything. I strongly assume that the Excel4-Macro does the same, but you will not find many persons around that are able to deal with Excel4-Macros.
Now to be able to read the value of a checkbox, you need to know if you are dealing with ActiveX or Form controls (or both). I wrote a small prove of concept that can deal with both. You pass the name of a workbook, the name (or number) of a sheet and an array with the name of the checkboxes you want to read. Result is an array with the values of the checkboxes. However you need to know that the values of an ActiveX-checkbox is True or False (or Null if you allow TripleState), while for a form-checkbox it is xlOn or xlOff. In the case a sheet doesn't have a checkbox with the specific name, it will return an arbitrary number
Function getCheckBoxValueFromFile(filename As String, sheet As Variant, checkboxNames) As Variant
Const undefinded = -999
Application.ScreenUpdating = False
Dim wb As Workbook
Set wb = Workbooks.Open(filename)
Dim i As Integer, res()
ReDim res(LBound(checkboxNames) To UBound(checkboxNames))
For i = LBound(checkboxNames) To UBound(checkboxNames)
Dim val As Long
val = undefinded
With wb.Sheets(sheet)
On Error Resume Next
' first try ActiveX-CheckBox
val = .OLEObjects(checkboxNames(i)).Object.Value
' if failed, try Form-CheckBox
If val = undefinded Then val = .CheckBoxes(checkboxNames(i)).Value
On Error GoTo 0
res(i) = val
End With
Next i
wb.Close False
getCheckBoxValueFromFile = res
Application.ScreenUpdating = True
End Function
To test the function:
Sub test()
Dim res, i, cbNames
cbNames = Array("CheckBox1", "Check Box 2")
res = getCheckBoxValueFromFile("C:\TEMP\Book1.xlsx", "Sheet1", cbNames)
For i = LBound(res) To UBound(res)
Debug.Print i & ": " & cbNames(i) & " -> " & res(i)
Next i
End Sub

VBScript Importing .txt file to .xlsx file [duplicate]

I'm trying to convert pipe-delimited files to xls (Excel) with batch file and vbscript. Unfortunately, my "output.xls" file is still showing the pipe delimiter in the table and the data are not organized.
srccsvfile = Wscript.Arguments(0)
tgtxlsfile = Wscript.Arguments(1)
'Create Spreadsheet
'Look for an existing Excel instance.
On Error Resume Next ' Turn on the error handling flag
Set objExcel = GetObject(,"Excel.Application")
'If not found, create a new instance.
If Err.Number = 429 Then '> 0
Set objExcel = CreateObject("Excel.Application")
End If
objExcel.Visible = false
objExcel.displayalerts=false
'Import CSV into Spreadsheet
Set objWorkbook = objExcel.Workbooks.open(srccsvfile)
Set objWorksheet1 = objWorkbook.Worksheets(1)
'Adjust width of columns
Set objRange = objWorksheet1.UsedRange
objRange.EntireColumn.Autofit()
'This code could be used to AutoFit a select number of columns
'For intColumns = 1 To 17
' objExcel.Columns(intColumns).AutoFit()
'Next
'Make Headings Bold
objExcel.Rows(1).Font.Bold = TRUE
'Freeze header row
With objExcel.ActiveWindow
.SplitColumn = 0
.SplitRow = 1
End With
objExcel.ActiveWindow.FreezePanes = True
'Add Data Filters to Heading Row
objExcel.Rows(1).AutoFilter
'set header row gray
objExcel.Rows(1).Interior.ColorIndex = 15
'-0.249977111117893
'Save Spreadsheet, 51 = Excel 2007-2010
objWorksheet1.SaveAs tgtxlsfile, 51
'Release Lock on Spreadsheet
objExcel.Quit()
Set objWorksheet1 = Nothing
Set objWorkbook = Nothing
Set ObjExcel = Nothing
source :http://www.tek-tips.com/viewthread.cfm?qid=1682555
Pipe doesn't equal Comma, Excel natively knows what to do with a CSV, but not with Pipe.
All is not lost, record your actions opening the file manually, once open highlight column A and click Data / Text To Columns, choose delimited and in the "other" box put a pipe then click next, choose the column formats (great to format numbers as text if you need to like Postcodes and phone numbers) then click finish.
Now stop the recorder and look at the code it generated. Port this over to your Excel object in your script.
Excel is a little picky when it comes to reading CSV files. If you have a delimited file with the extension .csv Excel will only open it correctly via the Open method if the delimiter is the character configured in the system's regional settings.
The Open method has optional parameters that allow you to specify a custom delimiter character (credit to #Jeeped for pointing this out):
set objWorkbook = objExcel.Workbooks.Open(srccsvfile, , , 6, , , , , "|")
You can also use the OpenText method (which will be used when recording the action as a macro):
objExcel.Workbooks.OpenText srccsvfile, , , 1, , , , , , , True, "|"
Set objWorkbook = objExcel.Workbooks(1)
Note that the OpenText method does not return a workbook object, so you must assign the workbook to a variable yourself after opening the file.
Important: either way your file must not have the extension .csv if your delimiter character differs from your system's regional settings, otherwise the delimiter will be ignored.

Run-Time Error '9': Subscript Out of Range when generating spreadsheet

I am currently trying to use an access database which uses vba to generate Excel spreadsheets and AutoCAD drawings; I didn't write the code, and I don't have experience coding in this language. When generating an excel file, the code gets to the line MyXL.Parent.Windows(1).Visible = True, it gives the error. The excel file is generated, but is identical to the template.
The File and directory names are placeholders
Dim MyXL As Object
FileCopy "\Directory\Template", "\Directory\Filename"
' This copies an Excel file, first half, then renames it with the Sales order number
Set MyXL = GetObject("\Directory\Template")
' This opens the Excel file named in the upper code second half
MyXL.Application.Visible = True
MyXL.Application.WindowState = 3
' MyXL1.Activate
MyXL.Parent.Windows(1).Visible = True
MyXL.Parent.ActiveWindow.WindowState = 2
With MyXL.Worksheets(1)
End With
At this point it sets a lot of values (I assume) in the form .Range("T60").Value = Me![Text516]
MyXL.Worksheets(1).Activate
MyXL.Save
MyXL.Parent.Quit ' This is what you have to do to close the Application
'MyXL.Parent.Quit
' MyXL.Parent.ActiveWindow.WindowState = xlMinimized
' MyXL.Close
The possible duplicate relates to copying an excel spreadsheet, however this problem goes further than that
Edit: I made a mistake and previously had the line Set MyXL = GetObject("\SameDirectory\SameFilename") but it is actually Set MyXL = GetObject("\Directory\Template")
Example of working code to open an Excel workbook, edit, save to a new name.
Sub CopyExcel()
Dim xl As Excel.Application, xlw As Excel.Workbook
Set xl = CreateObject("Excel.Application")
'the following two lines have same result
Set xlw = xl.Workbooks.Open("C:\Users\June\MyStuff\Condos.xlsx", , True)
'Set xlw1 = xl.Workbooks.Add("C:\Users\June\MyStuff\Condos.xlsx")
'code to edit
xlw.SaveAs "C:\Users\June\MyStuff\Condos2.xlsx"
xl.Quit
End Sub

Read data from a closed Excel workbook

I am trying to read data from several shared Excel documents without opening them. They are all in the same network directory except for the file I have written.
This is a sample of the data I am pulling:
=SUMPRODUCT(COUNTIFS('[Tracker_v1.2.xlsm]Work Log'!$D:$D,B5,'[Tracker_v1.2.xlsm]Work Log'!$J:$J,{"XXXX","YYYY"}))
=SUMPRODUCT(COUNTIFS('[B Tracker_v1.1.xlsm]Work Log'!$D:$D,B6,'[B Tracker_v1.1.xlsm]Work Log'!$J:$J,{"XXXX","YYYY"})+COUNTIFS('[A Tracker_v1.1.xlsm]Work Log'!$D:$D,B6,'[A Tracker_v1.1.xlsm]Work Log'!$J:$J,{"XXXX","YYYY"}))
I have tried using file paths '\\network path\[A Tracker_v1.1.xlsm]Work Log'!
Is there a way to read data without manually opening documents?
Since you don't want to open the files manually, I suspect you might accept to open them automatically. Here's a straightforward example on how to open and close some files and perform calculations using VBA. You will still technically open the files but only for a short moment, and without actually displaying them. For the sake of illustration, assume you have two files FileA.xlsm and FileB.xlsm in the folder "C:\MyPath\" with the following data in range A1 to A3:
FileA FileB
1 4444
22 55555
333 666666
The following code will print the sum of each column in the immediate window.
Sub OpenClosedFiles()
' Opens some files, does some calculations and then closes those files.
Application.ScreenUpdating = False ' Hide the files during the microseconds while they're open.
' Define the path:
Const sPath As String = "C:\MyPath\" ' <--- Replace; don't forget the last backslash.
Dim rngA, rngB As Range
Dim sFileA, sFileB As String
Dim wbA, wbB As Workbook
sFileA = "FileA.xlsm"
sFileB = "FileB.xlsm"
Set wbA = Workbooks.Open(sPath & sFileA)
Set wbB = Workbooks.Open(sPath & sFileB)
Set rngA = wbA.Worksheets(1).Range("A1:A3")
Set rngB = wbB.Worksheets(1).Range("A1:A3")
' Do calculations on the ranges here, for example:
Debug.Print "Sum of FileA: " & Application.WorksheetFunction.Sum(rngA)
Debug.Print "Sum of FileB: " & Application.WorksheetFunction.Sum(rngB)
wbA.Close
wbB.Close
Application.ScreenUpdating = True
End Sub
You can use ADO and the Excel ODBC driver to treat closed workbooks as databases. You can then use SQL to retrieve data. But it assumes that you have information laid out in tables with table headings. AFAIK that's the only way to deal with a spreadsheet without opening it.
There's a walk through here
Would it work to link to the closed files? (In Excel 2016, click Data > Get Data > From File > From Workbook.) Then the VBA code would be only ActiveWorkbook.RefreshAll.

Convert pipe-delimited files to .xls

I'm trying to convert pipe-delimited files to xls (Excel) with batch file and vbscript. Unfortunately, my "output.xls" file is still showing the pipe delimiter in the table and the data are not organized.
srccsvfile = Wscript.Arguments(0)
tgtxlsfile = Wscript.Arguments(1)
'Create Spreadsheet
'Look for an existing Excel instance.
On Error Resume Next ' Turn on the error handling flag
Set objExcel = GetObject(,"Excel.Application")
'If not found, create a new instance.
If Err.Number = 429 Then '> 0
Set objExcel = CreateObject("Excel.Application")
End If
objExcel.Visible = false
objExcel.displayalerts=false
'Import CSV into Spreadsheet
Set objWorkbook = objExcel.Workbooks.open(srccsvfile)
Set objWorksheet1 = objWorkbook.Worksheets(1)
'Adjust width of columns
Set objRange = objWorksheet1.UsedRange
objRange.EntireColumn.Autofit()
'This code could be used to AutoFit a select number of columns
'For intColumns = 1 To 17
' objExcel.Columns(intColumns).AutoFit()
'Next
'Make Headings Bold
objExcel.Rows(1).Font.Bold = TRUE
'Freeze header row
With objExcel.ActiveWindow
.SplitColumn = 0
.SplitRow = 1
End With
objExcel.ActiveWindow.FreezePanes = True
'Add Data Filters to Heading Row
objExcel.Rows(1).AutoFilter
'set header row gray
objExcel.Rows(1).Interior.ColorIndex = 15
'-0.249977111117893
'Save Spreadsheet, 51 = Excel 2007-2010
objWorksheet1.SaveAs tgtxlsfile, 51
'Release Lock on Spreadsheet
objExcel.Quit()
Set objWorksheet1 = Nothing
Set objWorkbook = Nothing
Set ObjExcel = Nothing
source :http://www.tek-tips.com/viewthread.cfm?qid=1682555
Pipe doesn't equal Comma, Excel natively knows what to do with a CSV, but not with Pipe.
All is not lost, record your actions opening the file manually, once open highlight column A and click Data / Text To Columns, choose delimited and in the "other" box put a pipe then click next, choose the column formats (great to format numbers as text if you need to like Postcodes and phone numbers) then click finish.
Now stop the recorder and look at the code it generated. Port this over to your Excel object in your script.
Excel is a little picky when it comes to reading CSV files. If you have a delimited file with the extension .csv Excel will only open it correctly via the Open method if the delimiter is the character configured in the system's regional settings.
The Open method has optional parameters that allow you to specify a custom delimiter character (credit to #Jeeped for pointing this out):
set objWorkbook = objExcel.Workbooks.Open(srccsvfile, , , 6, , , , , "|")
You can also use the OpenText method (which will be used when recording the action as a macro):
objExcel.Workbooks.OpenText srccsvfile, , , 1, , , , , , , True, "|"
Set objWorkbook = objExcel.Workbooks(1)
Note that the OpenText method does not return a workbook object, so you must assign the workbook to a variable yourself after opening the file.
Important: either way your file must not have the extension .csv if your delimiter character differs from your system's regional settings, otherwise the delimiter will be ignored.

Resources