I have an Excel file which has a macro and I would like to automate the process. I have Java code which fills the Excel columns and I have written the VBScript to run the macro in the Excel.
My Java code is (I pass the Excel fileName which has the macro)
public void excelupdate(String fileName) {
FileInputStream file = null;
FileOutputStream out = null;
try {
file = new FileInputStream(new File(fileName));
HSSFWorkbook yourworkbook = new HSSFWorkbook(file);
HSSFSheet sheet1 = null;
for (int i = 0; i < yourworkbook.getNumberOfSheets(); i++) {
if (yourworkbook.getSheetName(i).contains("Sheet-Macro")) {
sheet1 = yourworkbook.getSheetAt(i);
}
}
Cell cell = null;
int rowValue = 10;
for (int i = 0; i < list.size() - 1; i++) {
cell = sheet1.getRow(rowValue).getCell(2);
cell.setCellValue(list.get(i));
rowValue++;
}
Cell cell1 = null;
int rowValue1 = 10;
for (int j = 0; j < Input1list.size() - 1; j++) {
cell1 = sheet1.getRow(rowValue1).getCell(3);
cell1.setCellValue(Input1list.get(j));
rowValue1++;
}
Cell cell2 = null;
int rowValue2 = 22;
for (int k = 0; k < Input2list.size() - 1; k++) {
cell2 = sheet1.getRow(rowValue2).getCell(4);
cell2.setCellValue(Input2list.get(k));
rowValue2++;
}
out = new FileOutputStream(("C:\\Users\\Desktop\\EXCEL.xls"));
yourworkbook.write(out);
out.close();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (file != null) {
try {
file.close();
} catch (Exception e) {
}
}
if (out != null) {
try {
out.close();
} catch (Exception e) {
}
}
The Java code runs on Apache Poi to fill in the columns and moves the Excel file to a particular directory and then I have the below VBScript to run the macro:
Dim objXL
Set objXL = CreateObject("Excel.Application")
Set objWorkbook = objXL.Workbooks.Open("F:\testmacro\testmacro\EXCEL.xls")
objWorkbook.Sheets("AD stages").Cells(6, 4) = "F:\set1\set.txt"
objXL.Application.DisplayAlerts = False
objXL.ActiveWorkbook.Save
objXL.Application.Run "macro_cal"
objXL.ActiveWorkbook.Save
objXL.ActiveWorkbook.Close
objXL.Application.DisplayAlerts = True
objXL.Application.Quit
WScript.Echo "ExCEL file updated successfully"
WScript.Quit
Set objXL = Nothing
I call the above VBscript from the java as below,
File file = new File(excelFilename);
file.setExecutable(true);
file.setReadable(true);
file.setWritable(true);
Runtime runtime = Runtime.getRuntime();
try {
String sample="cmd /c start "+vbScript+" "+"\"" +excelFilename + "\"" + " "+"\"" +outFile + "\"";
System.out.println(sample);
Process process1 = runtime.exec(sample);
} catch (IOException e) {
logger.error(e);
}
But the problem is, once the Java populates the Excel columns and save the file, the file becomes protected and hence the VBScript is throwing an error stating it can't open/run the macro in protected Excel.
Any advice?
Thanks to #AxelRitcher, the solution is "Please read about Error message in Microsoft Office: "Office has detected a problem with this file". So seems as if the location F:\testmacro\testmacro is not a trusted location for Excel files having macros in it."
Related
i have some problem with my android app; i want that users could upload an excel file on Firebase and populate a RecyclerView with data on this file. I don't have problem about populate the RecyclerView, i know how to do it, i have problem on read the file. I uploaded it on Firebase with this:
StorageReference stRef = storageRef.child("clienti.xlsx");
UploadTask task = stRef.putFile(file);
task.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception exception) {
Toast.makeText(getActivity(), "Upload error: "+exception.getMessage() , Toast.LENGTH_SHORT).show();
}
}).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
#Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
downloadFile("clienti");
}
It all works until now, i also download the file from firebase to a specific folder but now i don't know how to "read" it and take data from it; i have tried this, but it said to me always that the file doesn't exists.
String[][] arrays = read( Environment.getExternalStorageDirectory() + localFile.getPath());
if(arrays == null){strHyouji="no such file";}else{
for (String[] array : arrays) {
for (String v : array) {
strHyouji = strHyouji + v + ",";
}
strHyouji = strHyouji + "\n";
aList.add(strHyouji);
}
}
Toast.makeText(getActivity(), strHyouji, Toast.LENGTH_SHORT).show();
Here the read() method:
Workbook workbook = null;
try {
WorkbookSettings ws = new WorkbookSettings();
ws.setGCDisabled(true);
workbook = Workbook.getWorkbook(new File(dbStr), ws);
Sheet sheet = workbook.getSheet(0);
int rowCount = sheet.getRows();
String[][] result = new String[rowCount][];
for (int i = 0; i < rowCount; i++) {
Cell[] row = sheet.getRow(i);
result[i] = new String[row.length];
for (int j = 0; j < row.length; j++) {
result[i][j] = row[j].getContents();
}
}
return result;
} catch (BiffException e) {
strHyouji=strHyouji+ e.toString();
} catch (IOException e) {
strHyouji=strHyouji+ e.toString();
} catch (Exception e) {
strHyouji=strHyouji+ e.toString();
} finally {
if (workbook != null) {
workbook.close();
}
}
return null;
With Apache POI, you can read the excel. Here ColumnHeaderString is the actual column header of the excel sheet and datafromcell is the value under the header converted to a String.
Reading the file
File file = new File( path ) // String file path
FileInputStream fileInputStream = new FileInputStream( file )
XSSFWorkbook workbook = new XSSFWorkbook( fileInputStream )
Using the workbook
XSSFSheet sheet = workbook.getSheetAt( 0 );
private DataFormatter excelDataFormatter = new DataFormatter()
Iterator<Row> rowIterator = sheet.rowIterator();
Row header = null;
if( rowIterator.hasNext() )
{
header = rowIterator.next();
}
while( rowIterator.hasNext() )
{
Iterator<Cell> cellIterator = row.cellIterator();
while( cellIterator.hasNext() )
{
Cell cell = cellIterator.next();
int cellIndex = cell.getColumnIndex();
String colHead = header.getCell( cellIndex ).toString();
if( ColumnHeaderString.equals( colHead ) ) // Match the desired column header
{
String datafromcell = excelDataFormatter.formatCellValue( cell ).strip();
}
}
}
I have the below code which exports a Jtable as Excel csv export.
I tried appending the file (boolean true), but the append happens within the same file itself.
public static boolean exportToCSV(JTable table,String pathToExportTo) {
try {
TableModel model = table.getModel();
FileWriter csv = new FileWriter(new File("C:/Users/user/Desktop/test.csv"));
for (int i = 0; i < model.getColumnCount(); i++) {
csv.write(model.getColumnName(i) + ",");
}
csv.write("\n");
for (int i = 0; i < model.getRowCount(); i++) {
for (int j = 0; j < model.getColumnCount(); j++) {
csv.write(model.getValueAt(i, j).toString() + ",");
}
csv.write("\n");
}
csv.close();
JOptionPane.showMessageDialog(null,"Export Successful!");
return true;
} catch (IOException e) {
e.printStackTrace();
JOptionPane.showMessageDialog(null,"Error! Excel cannot be exported!");
}
return false;
This is working fine, but this overwrites the existing file. I would want this to be exported as a different file and probably rename as text(1).csv
You could use a method to compute report output file:
File resolveFileName(){
String directory ="C:/Users/user/Desktop/";
File res = new File(directory + "test.csv");
if(!res.exists()){
return res;
}
int filesInDirectoryCount = (new File(directory)).listFiles().length;
String fileName = "test_"+filesInDirectoryCount+".csv";
return new File(directory+fileName);
}
Usage:
FileWriter csv = new FileWriter(resolveFileName);
This will add a numer to the file name, based on numer of files in this directory. So it should help with this problem.
I am doing Bulk Upload Task in Alfresco.
Before this i created custom action to call java code, i also successfully read data from excel sheet, and i found node reference of target document as well as source Document. Using that node reference i am also able to create new multiple Documents.
Now My requirement is, I want to replace Excel Data in that newly created Document. I tried to replace it, But It replacing the String only in First line of document, and it also deleting Rest of the existing contents inside newly created document. I have written Below code for this.
In below code i am first simply trying to replace some hard coded data to the Document.
But My requirement is i want to replace the data inside document which i already read from excel file.
Java Code:
public class MoveReplacedActionExecuter extends ActionExecuterAbstractBase {
InputStream is;
Cell cell = null;
public static final String NAME = "move-replaced";
private FileFolderService fileFolderService;
private NodeService nodeService;
private ContentService contentService;
private SearchService searchService;
#Override
protected void addParameterDefinitions(List < ParameterDefinition > paramList) {
}
public void executeImpl(Action ruleAction, NodeRef actionedUponNodeRef) {
try {
ContentReader contentReader = contentService.getReader(actionedUponNodeRef, ContentModel.PROP_CONTENT);
is = contentReader.getContentInputStream();
} catch (NullPointerException ne) {
System.out.println("Null Pointer Exception" + ne);
}
try {
Workbook workbook = new XSSFWorkbook(is);
Sheet firstSheet = workbook.getSheetAt(0);
Iterator < Row > iterator = firstSheet.rowIterator();
while (iterator.hasNext()) {
ArrayList < String > al = new ArrayList < > ();
System.out.println("");
Row nextRow = iterator.next();
Iterator < Cell > cellIterator = nextRow.cellIterator();
while (cellIterator.hasNext()) {
cell = cellIterator.next();
switch (cell.getCellType()) {
case Cell.CELL_TYPE_STRING:
System.out.print("\t" + cell.getStringCellValue());
al.add(cell.getStringCellValue());
break;
case Cell.CELL_TYPE_BOOLEAN:
System.out.print("\t" + cell.getBooleanCellValue());
al.add(String.valueOf(cell.getBooleanCellValue()));
break;
case Cell.CELL_TYPE_NUMERIC:
System.out.print("\t" + cell.getNumericCellValue());
al.add(String.valueOf(cell.getNumericCellValue()));
break;
}
}
}
is.close();
} catch (Exception e) {
e.printStackTrace();
}
String query = "PATH:\"/app:company_home/cm:Dipak/cm:OfferLetterTemplate.doc\"";
SearchParameters sp = new SearchParameters();
StoreRef storeRef = new StoreRef(StoreRef.PROTOCOL_WORKSPACE, "SpacesStore");
sp.addStore(storeRef);
sp.setLanguage(SearchService.LANGUAGE_LUCENE);
sp.setQuery(query);
ResultSet resultSet = searchService.query(sp);
System.out.println("Result Set" + resultSet.length());
NodeRef sourceNodeRef = null;
for (ResultSetRow row: resultSet) {
NodeRef currentNodeRef = row.getNodeRef();
sourceNodeRef = currentNodeRef;
System.out.println(currentNodeRef.toString());
}
NodeRef n = new NodeRef("workspace://SpacesStore/78342318-37b8-4b42-aadc-bb0ed5d413d9");
try {
org.alfresco.service.cmr.model.FileInfo fi = fileFolderService.copy(sourceNodeRef, n, "JustCreated" + Math.random() + ".doc");
NodeRef newNode = fi.getNodeRef();
QName TYPE_AUTHORTY = QName.createQName("sunpharma.hr.model", "hrdoctype");
nodeService.setType(newNode, TYPE_AUTHORTY);
ContentReader contentReader1 = contentService.getReader(newNode, ContentModel.PROP_CONTENT);
InputStream is2 = contentReader1.getContentInputStream();
POIFSFileSystem fs = new POIFSFileSystem(is2);
HWPFDocument doc = new HWPFDocument(fs);
doc = replaceText1(doc, "Company", "Datamatics");
ContentWriter writerDoc = contentService.getWriter(newNode, ContentModel.PROP_CONTENT, true);
writerDoc.putContent(doc.getDocumentText());
} catch (FileExistsException | FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private static HWPFDocument replaceText1(HWPFDocument doc, String findText, String replaceText) {
System.out.println("In the method replacetext" + replaceText);
Range r1 = doc.getRange();
System.out.println("Range of Doc : " + r1);
for (int i = 0; i < r1.numSections(); ++i) {
Section s = r1.getSection(i);
for (int x = 0; x < s.numParagraphs(); x++) {
Paragraph p = s.getParagraph(x);
for (int z = 0; z < p.numCharacterRuns(); z++) {
CharacterRun run = p.getCharacterRun(z);
String text = run.text();
if (text.contains(findText)) {
run.replaceText(findText, replaceText);
} else {
System.out.println("NO text found");
}
}
}
}
return doc;
}
public void setFileFolderService(FileFolderService fileFolderService) {
this.fileFolderService = fileFolderService;
}
public void setNodeService(NodeService nodeService) {
this.nodeService = nodeService;
}
public void setContentService(ContentService contentService) {
this.contentService = contentService;
}
public void setSearchService(SearchService searchService) {
this.searchService = searchService;
}
}
Its not possible to take direct file stream object in alfresco.
so i created one file at local drive, in background i performed all replacement operations. and after that i read all data using file input stream object. and later i used file that stream with node.
and it gave me my desired output. :)
I need to set a value for a specific row and column of the spreadsheet, but I get a null pointer before even i = 1. I've tried changing the code but this error keeps happening and I have no more idea why.Does anyone have any idea why this happens?
My code
public Workbook build(Planilha planilha) {
File file = new File(TEMPLATE_PATH);
if (!file.exists()) {
Log.error(this, String.format("File %s not exists.", file.getAbsolutePath()));
throw new NotFoundException("File not exists.");
}
Workbook wb = null;
try (FileInputStream fs = new FileInputStream(file)) {
wb = new XSSFWorkbook(fs);
wb = writeMetadatas(planilha, wb);
Map<String, Integer> header = getHeader(wb);
Sheet sheet = wb.getSheetAt(0);
Row row;
Cell cell;
for (int i = 0; i <= 10; i++) {
row = sheet.getRow(i);
for (int j = 0; j <= 10; j++) {
cell = row.getCell(j, Row.CREATE_NULL_AS_BLANK);
if (cell.getColumnIndex() == 0 && row.getRowNum() == 7) {
cell.setCellValue("teste");
}
}
}
} catch (Exception e) {
Log.error(this, "Erro: Planilha não existe", e);
System.err.print("Erro");
}
String tmpDir = System.getProperty("java.io.tmpdir");
File f = FileUtil.file(PATH, System.currentTimeMillis() + ".xlsx");
try {
FileOutputStream fout = new FileOutputStream(f);
wb.write(fout);
fout.flush();
fout.close();
} catch (Exception e) {
Log.error(this, "Erro ao abrir arquivo p escrever.");
}
return wb;
}
**NullPointer happens in cell.setCellValue("teste");
I'm trying to set that cell
First, you can test if the row number is a certain number outside of your for loop that loops over the cells in a row. Pull that if outside your j for loop.
It looks like the Cell doesn't exist. row.getCell(j) is returning null.
You can use a MissingCellPolicy to determine whether you want to return a new Cell if the Cell doesn't already exist. The CREATE_NULL_AS_BLANK value will create a blank Cell for you if it doesn't already exist.
I am trying to open a file by drag and drop onto JTextField but i always get the error.
Heres my code
public void drop(DropTargetDropEvent dtde) {
String str4=null;
try {
JTextArea comp = null;
if(Switchtab==2)
comp=textarea1;
if(Switchtab==3)
comp=textarea2;
if(Switchtab==4)
comp=textarea3;
if(Switchtab==1)
comp=textarea4;
// Ok, get the dropped object and try to figure out what it is
Transferable tr = dtde.getTransferable();
DataFlavor[] flavors = tr.getTransferDataFlavors();
for (int i = 0; i < flavors.length; i++) {
System.out.println("Possible flavor: "
+ flavors[i].getMimeType());
// Check for file lists specifically
if (flavors[i].isFlavorJavaFileListType()) {
// Great! Accept copy drops...
dtde.acceptDrop(DnDConstants.ACTION_COPY);
// comp.setText("Successful file list drop.\n\n");
// And add the list of file names to our text area
java.util.List list = (java.util.List) tr
.getTransferData(flavors[i]);
for (int j = 0; j < list.size(); j++) {
//wcomp.append(list.get(j) + "\n");
str4=list.get(j)+"\n";
}
// Replace '\' with '/'
file_pth = str4.replaceAll("\\\\","/" );
System.out.println(str4.replaceAll("\\\\","/" ));
//Open the file
try {
File f = new File(file_pth);
FileInputStream fobj = new FileInputStream(f);
int len = (int) f.length();
str4 = "";
for (int j = 0; j < len; j++) {
char str5 = (char) fobj.read();
str4 = str4 + str5;
}
comp.setText(str4);
setTitle(str4);
} catch (Exception e) {
System.out.println("Caught::" + e);
}
// If we made it this far, everything worked.
dtde.dropComplete(true);
return;
}
}
// Hmm, the user must not have dropped a file list
System.out.println("Drop failed: " + dtde);
dtde.rejectDrop();
} catch (Exception e) {
e.printStackTrace();
dtde.rejectDrop();
}
}
I even tried replacing backslash with double backslash and forward slash but still i get this error
Possible flavor: application/x-java-file-list; class=java.util.List
C:/kevin_java/file io/DemoIO.java
Caught::java.io.FileNotFoundException: C:\kevin_java\file io\DemoIO.java
(The filename, directory name, or volume label syntax is incorrect)
The output doesnt show the replaced string.
It shows the previous string with single backslash.
finally i got my answer.
Simple solution
java.util.List list = (java.util.List) tr
.getTransferData(flavors[i]);
for (int j = 0; j < list.size(); j++) {
str4=list.get(j).toString();
}
File f = new File(str4);
FileInputStream fobj = new FileInputStream(f);
...
...
..
Edit
From the javadoc for isFlavorJavaFileListType,
Returns true if the DataFlavor specified represents a list of file objects.
Therefor,
FileInputStream fobj = new FileInputStream(list.get(list.length()-1));