How to read result of HYPERLINK() function in POI - apache-poi

Apache Poi can evaluate and return results of functions in formulas. However for the special function HYPERLINK(), it only returns the "display value", not the actual calculated hyperlink value.
I have an Excel file which contains complex computed hyperlinks which combine results from a number of different fields in the workbook, thus it would be nice to be able to read the resulting URL for the hyperlink, however with default formula evaluation I only get the "display value", not the actual URL.
Is there a way I can compute the formula in a way so I can read the actual URL?

Found a way, but I would probably call it "ugly workaround":
If you try to re-implement the "Hyperlink" function implementation in Apache Poi with WorkbookEvaluator.registerFunction("HYPERLINK", func) you get an error that the built-in function cannot be overwritten.
After digging into Poi a bit more, I found that I can access the list of builtin-functions by putting a class into the "org.apache.poi.ss.formula.eval" package:
package org.apache.poi.ss.formula.eval;
public class BuiltinFunctionsOverloader {
public static void replaceBuiltinFunction(int index, Function function) {
FunctionEval.functions[index] = function;
}
}
Then I can use this override a function, e.g. Hyperlink has index 359:
BuiltinFunctionsOverloader.replaceBuiltinFunction(359, func);
With a function implementation as follows, I now get the URL-value instead of the display-value:
Function func = new Function2Arg() {
#Override
public final ValueEval evaluate(ValueEval[] largs, int srcRowIndex, int srcColumnIndex) {
switch (largs.length) {
case 1:
return evaluate(srcRowIndex, srcColumnIndex, largs[0]);
case 2:
return evaluate(srcRowIndex, srcColumnIndex, largs[0], largs[1]);
}
return ErrorEval.VALUE_INVALID;
}
public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0) {
return arg0;
}
#Override
public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1) {
return arg0;
}
};
Ugly, but at least does not require me to patch POI.
Anybody knows of a more "official" way of doing this?

Related

How can I change the Table class names using the by extending jOOQ's DefaultGeneratorStrategy?

I am using the jooq codgen gradle plugin to change the naming convention for generated tables to include Table at the end of the class name. However, I am not sure how to distinguish a table from a schema in the generator.
My naming override is:
#Override
public String getJavaClassName(Definition definition, Mode mode) {
String result = super.getJavaClassName(definition, mode);
if (mode == Mode.DEFAULT) {
result += "Table";
}
return result;
}
Is there a way to determine If the current object extends TableImpl or maybe I need to take a different approach?
Just use instanceof checks on your definition, like this:
#Override
public String getJavaClassName(Definition definition, Mode mode) {
String result = super.getJavaClassName(definition, mode);
if (mode == Mode.DEFAULT && definition instanceof TableDefinition) {
result += "Table";
}
return result;
}

Javafx PropertyValueFactory not populating Tableview

This has baffled me for a while now and I cannot seem to get the grasp of it. I'm using Cell Value Factory to populate a simple one column table and it does not populate in the table.
It does and I click the rows that are populated but I do not see any values in them- in this case String values. [I just edited this to make it clearer]
I have a different project under which it works under the same kind of data model. What am I doing wrong?
Here's the code. The commented code at the end seems to work though. I've checked to see if the usual mistakes- creating a new column instance or a new tableview instance, are there. Nothing. Please help!
//Simple Data Model
Stock.java
public class Stock {
private SimpleStringProperty stockTicker;
public Stock(String stockTicker) {
this.stockTicker = new SimpleStringProperty(stockTicker);
}
public String getstockTicker() {
return stockTicker.get();
}
public void setstockTicker(String stockticker) {
stockTicker.set(stockticker);
}
}
//Controller class
MainGuiController.java
private ObservableList<Stock> data;
#FXML
private TableView<Stock> stockTableView;// = new TableView<>(data);
#FXML
private TableColumn<Stock, String> tickerCol;
private void setTickersToCol() {
try {
Statement stmt = conn.createStatement();//conn is defined and works
ResultSet rsltset = stmt.executeQuery("SELECT ticker FROM tickerlist order by ticker");
data = FXCollections.observableArrayList();
Stock stockInstance;
while (rsltset.next()) {
stockInstance = new Stock(rsltset.getString(1).toUpperCase());
data.add(stockInstance);
}
} catch (SQLException ex) {
Logger.getLogger(WriteToFile.class.getName()).log(Level.SEVERE, null, ex);
System.out.println("Connection Failed! Check output console");
}
tickerCol.setCellValueFactory(new PropertyValueFactory<Stock,String>("stockTicker"));
stockTableView.setItems(data);
}
/*THIS, ON THE OTHER HAND, WORKS*/
/*Callback<CellDataFeatures<Stock, String>, ObservableValue<String>> cellDataFeat =
new Callback<CellDataFeatures<Stock, String>, ObservableValue<String>>() {
#Override
public ObservableValue<String> call(CellDataFeatures<Stock, String> p) {
return new SimpleStringProperty(p.getValue().getstockTicker());
}
};*/
Suggested solution (use a Lambda, not a PropertyValueFactory)
Instead of:
aColumn.setCellValueFactory(new PropertyValueFactory<Appointment,LocalDate>("date"));
Write:
aColumn.setCellValueFactory(cellData -> cellData.getValue().dateProperty());
For more information, see this answer:
Java: setCellValuefactory; Lambda vs. PropertyValueFactory; advantages/disadvantages
Solution using PropertyValueFactory
The lambda solution outlined above is preferred, but if you wish to use PropertyValueFactory, this alternate solution provides information on that.
How to Fix It
The case of your getter and setter methods are wrong.
getstockTicker should be getStockTicker
setstockTicker should be setStockTicker
Some Background Information
Your PropertyValueFactory remains the same with:
new PropertyValueFactory<Stock,String>("stockTicker")
The naming convention will seem more obvious when you also add a property accessor to your Stock class:
public class Stock {
private SimpleStringProperty stockTicker;
public Stock(String stockTicker) {
this.stockTicker = new SimpleStringProperty(stockTicker);
}
public String getStockTicker() {
return stockTicker.get();
}
public void setStockTicker(String stockticker) {
stockTicker.set(stockticker);
}
public StringProperty stockTickerProperty() {
return stockTicker;
}
}
The PropertyValueFactory uses reflection to find the relevant accessors (these should be public). First, it will try to use the stockTickerProperty accessor and, if that is not present fall back to getters and setters. Providing a property accessor is recommended as then you will automatically enable your table to observe the property in the underlying model, dynamically updating its data as the underlying model changes.
put the Getter and Setter method in you data class for all the elements.

When to use C# out keyword on parameter

I've seen some developers use the out keyword on parameter lists of void functions. I'm quite unclear on what the pros and cons are of code below:
List<string> listOfResult;
public void public void (out listOfResult)
{
//bla bla
}
versus
public List<string> c(out listOfResult)
{
List<string> list= new List<string>();
//bla bla
return list;
}
Are these two code snippets perfectly valid or is there any catch around the out keyword?
out keyword is handy when you need to return more than one value from function. Nice example is TryXXX methods, which return status of operation instead of throwing exceptions:
public bool TryParse(string str, out int value);
But I don't see any reason to use single out parameter with void methods... Simply return that value from your method. It will be much easier to use. Compare:
List<string> list;
GetList(out list); // confusing method name
With
List<string> list = GetList(); // nice name, one line of code
If getting of list could throw exceptions, then you can create method like this:
List<string> list;
if (TryGetList(out list)) // better than exception handling
{
// list was filled successfully
}
out parameters are quite handy when you need to return more than one value from a function.
e.g.
Return is a list of results, but you can use an out parameter to return an error message in the case when the list being returned is null.
It's a nice syntax to return multiple parameters. I personally think it's almost always better to model the return of the method as a "new object/class".
That would be:
class CResult
{
List<string> firstResult;
List<string> secondResult;
}
public CResult c()
{
// do something
return new CResult() {firstResult = ..., secondResult = ... };
}
You can see more things related to this approach here.
//out key word is used in function instead of return. we can use multiple parameters by using out key word
public void outKeyword(out string Firstname, out string SecondName)
{
Firstname = "Muhammad";
SecondName = "Ismail";
}
//on button click Event
protected void btnOutKeyword_Click(object sender, EventArgs e)
{
string first, second;
outKeyword(out first, out second);
lblOutKeyword.Text = first + " " + second;
}

Generic used in conjunction with Sort(Comparison<T>)

Im wondering if its possible to reuse my overload of the Sort(Comparison) method to sort both labels and textboxes by tabIndex. Ive already tried and i couldnt get it to work. Any help would be appreciated.
foreach(Control control in gbUserInputs.Controls)
{
if (control is Label)
{
inputLabels.Add((Label)control);
}
if (control is TextBox)
{
inputTxtboxes.Add((TextBox)control);
}
}
Sort method call(this doesnt work).
inputLabels.Sort(sortMyInputs<Label>);
Overload of sort method.
private static int sortMyInputs<T>(T entry1, T entry2)
{
return entry1.TabIndex.CompareTo(entry2.TabIndex);
}
You shouldn't be making a generic method:
private static int CompareLabels(Label entry1, Label entry2)
{
return entry1.TabIndex.CompareTo(entry2.TabIndex);
}
The point of a generic delegate is to allow it to hold methods of different concrete types; not to allow it to hold methods that are themselves generic.
If you want to reuse your method, you can modify it to take Control (which both TextBox and Label inherit); you would still be able to pass it to List<Label>.Sort because of delegate covariance.
If you're using .Net < 4, which doesn't have delegate covariance, you can do it your way by adding a constraint to the method so that it knows what T can be:
private static int CompareLabels<T>(T entry1, T entry2) where T : Control
{
return entry1.TabIndex.CompareTo(entry2.TabIndex);
}
You can also simply replace all of your code with one line of LINQ:
inputLabels = gbUserInputs.Controls.OfType<Label>()
.OrderBy(c => c.TabIndex)
.ToList();

How to search Lucene.NET without indicating "top n" hits limit?

There are several overloads of IndexSearcher.Search method in Lucene. Some of them require "top n hits" argument, some don't (these are obsolete and will be removed in Lucene.NET 3.0).
Those, which require "top n" argument actually cause memory preallocation for this entire posible range of results. So when you're in situation when you can't even approximately estimate count of results returned, the only opportunity is to pass a random large number to ensure that all query results will be returned. This causes severe memory pressure and leaks due to LOH fragmentation.
Is there an oficial not outdated way to search without passing "top n" argument?
Thanks in advance, guys.
I'm using Lucene.NET 2.9.2 as reference point for this answer.
You could build a custom collector which you pass to one of the search overloads.
using System;
using System.Collections.Generic;
using Lucene.Net.Index;
using Lucene.Net.Search;
public class AwesomeCollector : Collector {
private readonly List<Int32> _docIds = new List<Int32>();
private Scorer _scorer;
private Int32 _docBase;
public IEnumerable<Int32> DocumentIds {
get { return _docIds; }
}
public override void SetScorer(Scorer scorer) {
_scorer = scorer;
}
public override void Collect(Int32 doc) {
var score = _scorer.Score();
if (_lowerInclusiveScore <= score)
_docIds.Add(_docBase + doc);
}
public override void SetNextReader(IndexReader reader, Int32 docBase) {
_docBase = docBase;
}
public override bool AcceptsDocsOutOfOrder() {
return true;
}
}

Resources