I am trying to write a function that determines if two strings are anagrams of each other. I give the function two strings that are equal except for case, and it fails, even though I ignore case in my comparison.
Test case:
hello
Hello
for these input my output is NOT an anagram, but it is an anagram
SOURCE CODE:
static boolean isAnagram(String a, String b) {
char[] a1 = a.toCharArray();
char[] b1 = b.toCharArray();
Arrays.sort(a1);
Arrays.sort(b1);
String x = new String(a1);
String y = new String(b1);
int i=0,flag=0;
while(i < a1.length)
{
if(x.equalsIgnoreCase(y)){
i++;
}
else
return false;
}
return true;
}
You do not need the while loop;
static boolean isAnagram(String a, String b) {
char []a1= a.toLowerCase().toCharArray();
char []b1= b.toLowerCase().toCharArray();
Arrays.sort(a1);
Arrays.sort(b1);
String x= new String(a1), y = new String(b1);
return x.equals(y);
}
Check out the below methods for Anagram Check:
/**
* Java program - String Anagram Example.
* This program checks if two Strings are anagrams or not
*/
public class AnagramCheck {
/*
* One way to find if two Strings are anagram in Java. This method
* assumes both arguments are not null and in lowercase.
*
* #return true, if both String are anagram
*/
public static boolean isAnagram(String word, String anagram){
if(word.length() != anagram.length()){
return false;
}
char[] chars = word.toCharArray();
for(char c : chars){
int index = anagram.indexOf(c);
if(index != -1){
anagram = anagram.substring(0,index) + anagram.substring(index +1, anagram.length());
}else{
return false;
}
}
return anagram.isEmpty();
}
/*
* Another way to check if two Strings are anagram or not in Java
* This method assumes that both word and anagram are not null and lowercase
* #return true, if both Strings are anagram.
*/
public static boolean iAnagram(String word, String anagram){
char[] charFromWord = word.toCharArray();
char[] charFromAnagram = anagram.toCharArray();
Arrays.sort(charFromWord);
Arrays.sort(charFromAnagram);
return Arrays.equals(charFromWord, charFromAnagram);
}
public static boolean checkAnagram(String first, String second){
char[] characters = first.toCharArray();
StringBuilder sbSecond = new StringBuilder(second);
for(char ch : characters){
int index = sbSecond.indexOf("" + ch);
if(index != -1){
sbSecond.deleteCharAt(index);
}else{
return false;
}
}
return sbSecond.length()==0 ? true : false;
}
}
I am trying to port a Java application for use in node.js, and am running into an issue with Object inheritance. I have a base object HVal, and 2 subclasses, HBin and HBool. When I try to use both HBin and HBool, the 1st object that is loaded is overridden by the 2nd object that is loaded, even though they are being assigned to different vars. Anyone have an idea of what is going on here.
HVal.js
/** Package private constructor */
function HVal() {};
/** Abstract functions that must be defined in inheriting classes
* hashCode: int - Hash code is value based
* toZinc: String - Encode value to zinc format
* equals: boolean - Equality is value based
*/
/** String - String format is for human consumption only */
HVal.prototype.toString = function() { return this.toZinc(); };
/** int - Return sort order as negative, 0, or positive */
HVal.prototype.compareTo = function(that) { return this.toString().localeCompare(that); };
/** boolean - check for type match */
HVal.prototype.typeis = function (check, prim, obj) { return typeof(check)==prim || check instanceof obj; };
/** Add hashCode function to Javascript String object */
String.prototype.hashCode = function() {
var hash = 0, i, chr, len;
if (this.length == 0) return hash;
for (i = 0, len = this.length; i < len; i++) {
chr = this.charCodeAt(i);
hash = ((hash << 5) - hash) + chr;
hash |= 0; // Convert to 32bit integer
}
return hash;
};
/** Export for use in other modules */
module.exports = new HVal();
HBin.js
var hval = require('./HVal');
/** Private constructor */
function HBin(mime) {
/** MIME type for binary file */
this.mime = mime;
};
HBin.prototype = hval;
/** Construct for MIME type */
HBin.prototype.make = function(mime) {
if (!hval.typeis(mime, 'string', String) || mime.length == 0 || mime.indexOf('/') < 0)
throw new Error("Invalid mime val: \"" + mime + "\"");
return new HBin(mime);
};
/** int - Hash code is based on mime field */
HBin.prototype.hashCode = function() { return mime.hashCode(); };
/** String - Encode as "Bin(<mime>)" */
HBin.prototype.toZinc = function() {
var s = "Bin(";
for (var i=0; i<this.mime.length; ++i)
{
var c = this.mime.charAt(i);
if (c > 127 || c == ')') throw new Error("Invalid mime, char='" + c + "'");
s += c;
}
s += ")";
return s.toString();
};
/** boolean - Equals is based on mime field */
HBin.prototype.equals = function(that) {
if (!typeOf(that) == HBin) return false;
return this.mime === that.mime;
};
/** Export for use in other modules */
module.exports = new HBin();
HBool.js
var hval = require('./HVal');
/** Private constructor */
function HBool(val) {
/** Boolean value */
this.val = val;
};
HBool.prototype = hval;
/** Construct from boolean value */
HBool.prototype.make = function(val) {
if (!hval.typeis(val, 'boolean', Boolean))
throw new Error("Invalid boolean val: \"" + val + "\"");
return new HBool(val);
};
/** int - Hash code is same as java.lang.Boolean */
HBool.prototype.hashCode = function() { return this.val ? 1231 : 1237; };
/** String - Encode as T/F */
HBool.prototype.toZinc = function() { return this.val ? "T" : "F"; };
/** boolean - Equals is based on reference */
HBool.prototype.equals = function(that) { return this === that; };
/** String - String format is for human consumption only */
HBool.prototype.toString = function() { return this.val ? "true" : "false"; };
/** Export for use in other modules */
module.exports = new HBool();
index.js
var hbin = require('./HBin');
var hbool = require('./HBool');
console.log('BIN: ' + hbin.make("test/test").toString());
console.log();
console.log('T: ' + hbool.make(true).toString());
console.log('F: ' + hbool.make(false).toString());
Output - failing on first console.log
HBool.js:19
throw new Error("Invalid boolean val: \"" + val + "\"");
Error: Invalid boolean val: "test/test"
at HVal.HBool.make (HBool.js:19:11)
at Object.<anonymous> (index.js:4:28)
...
The issue has to do with how you're exporting from a module and how you're assigning the prototype when you want to inherit and the issue is subtle. There are a couple things going on here. First off, module.exports is cached for modules, so every time you do:
var hval = require('./HVal');
you are getting the exact same HVal instantiated object back each time and you can never make a different object because you didn't export the constructor. That is a problem for all your modules. You should export the constructor function and let the user of the module actually create new instances of your object with new.
You can do that by changing:
module.exports = new HVal();
to:
module.exports = HVal;
And, then when you require() it, you just get the constructor:
var HVal = require('./HVal');
var HBool = require('./HBool');
And, then you can create an HBool object like this:
var hbool = new HBool();
This issue then seems to be messing up your inheritance when you assign something like:
HBool.prototype = hval;
The problem is entirely fixed if you export the constructors themselves and then change the above prototype assignment to use Object.create:
HBool.prototype = Object.create(HVal.prototype);
You can see a working demo here (modules removed to make the demo easier to show): http://jsfiddle.net/jfriend00/ty5wpkqm/
I also made another correction to the code. Instead of this:
if (!hval.typeis(mime, 'string', String) || mime.length == 0 || mime.indexOf('/') < 0)
I changed it to actually use the inherited methods on this object:
if (!this.typeis(mime, 'string', String) || mime.length == 0 || mime.indexOf('/') < 0)
This is the proper way to call methods on the current object (even inherited methods). Now, this happens to be a static method (it doesn't use the instance at all so you could move it off the object entirely, but since you have declared it on the object, you should refer to it as this.typeis().
I also noticed that your .equals() method is not correct. You have this:
/** boolean - Equals is based on mime field */
HBin.prototype.equals = function(that) {
if (!typeOf(that) == HBin) return false;
return this.mime === that.mime;
};
First off, did you create a new global function called typeOf()? The built-in mechanism in Javascript is lowercase typeof. Second off, typeof(that) will never be HBin. Objects in Javascript don't report a type like that. An object would report typeof(that) === "object". You can perhaps use instanceof:
/** boolean - Equals is based on mime field */
HBin.prototype.equals = function(that) {
return that instanceof HBin && this.mime === that.mime;
};
I am struggling with an intermittent C++ application crash.
I am not a C++ programmer but am tasked with solving this problem, so very much hope you can help me.
Often the app runs fine, then on occasion crashes with an exception.
When entering debug from running the exe, line of code as seen highlighted seems to be at fault - please see first screen shot.
I have expanded some of the Locals in the second screen shot.
This line of code calls a function 'ClearVariant' the code being as follows for this function:
/*
* ClearVariant
*
* Zeros a variant structure without regard to current contents
*/
void CXLAutomation::ClearVariant(VARIANTARG *pvarg)
{
pvarg->vt = VT_EMPTY;
pvarg->wReserved1 = 0;
pvarg->wReserved2 = 0;
pvarg->wReserved3 = 0;
pvarg->lVal = 0;
}
The entire cpp file is at the end of the post.
The OpenExcelFile is function that leads to this problem - as you can from the call stack in the screen shots.
// XLAutomation.cpp: implementation of the CXLAutomation class.
//This is C++ modification of the AutoXL C-sample from
//Microsoft Excel97 Developer Kit, Microsoft Press 1997
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
//#include "XLAutomationTester.h"
#include "XLAutomation.h"
#include <ole2ver.h>
#include <string.h>
#include <winuser.h>
#include <stdio.h>
#include <string>
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
/*
* Arrays of argument information, which are used to build up the arg list
* for an IDispatch call. These arrays are statically allocated to reduce
* complexity, but this code could be easily modified to perform dynamic
* memory allocation.
*
* When arguments are added they are placed into these arrays. The
* Vargs array contains the argument values, and the lpszArgNames array
* contains the name of the arguments, or a NULL if the argument is unnamed.
* Flags for the argument such as NOFREEVARIANT are kept in the wFlags array.
*
* When Invoke is called, the names in the lpszArgNames array are converted
* into the DISPIDs expected by the IDispatch::Invoke function. The
* IDispatch::GetIDsOfNames function is used to perform the conversion, and
* the resulting IDs are placed in the DispIds array. There is an additional
* slot in the DispIds and lpszArgNames arrays to allow for the name and DISPID
* of the method or property being invoked.
*
* Because these arrays are static, it is important to call the ClearArgs()
* function before setting up arguments. ClearArgs() releases any memory
* in use by the argument array and resets the argument counters for a fresh
* Invoke.
*/
//int m_iArgCount;
//int m_iNamedArgCount;
//VARIANTARG m_aVargs[MAX_DISP_ARGS];
//DISPID m_aDispIds[MAX_DISP_ARGS + 1]; // one extra for the member name
//LPOLESTR m_alpszArgNames[MAX_DISP_ARGS + 1]; // used to hold the argnames for GetIDs
//WORD m_awFlags[MAX_DISP_ARGS];
//////////////////////////////////////////////////////////////////////
CXLAutomation::CXLAutomation()
{
m_pdispExcelApp = NULL;
m_pdispWorkbook = NULL;
m_pdispWorksheet = NULL;
m_pdispActiveChart = NULL;
InitOLE();
StartExcel();
//SetExcelVisible(TRUE);
//CreateWorkSheet();
//CreateXYChart();
}
CXLAutomation::CXLAutomation(BOOL bVisible)
{
m_pdispExcelApp = NULL;
m_pdispWorkbook = NULL;
m_pdispWorksheet = NULL;
m_pdispActiveChart = NULL;
InitOLE();
StartExcel();
SetExcelVisible(bVisible);
CreateWorkSheet();
//CreateXYChart();
}
CXLAutomation::~CXLAutomation()
{
//ReleaseExcel();
ReleaseDispatch();
OleUninitialize();
}
BOOL CXLAutomation::InitOLE()
{
DWORD dwOleVer;
dwOleVer = CoBuildVersion();
// check the OLE library version
if (rmm != HIWORD(dwOleVer))
{
MessageBox(NULL, _T("Incorrect version of OLE libraries."), "Failed", MB_OK | MB_ICONSTOP);
return FALSE;
}
// could also check for minor version, but this application is
// not sensitive to the minor version of OLE
// initialize OLE, fail application if we can't get OLE to init.
if (FAILED(OleInitialize(NULL)))
{
MessageBox(NULL, _T("Cannot initialize OLE."), "Failed", MB_OK | MB_ICONSTOP);
return FALSE;
}
return TRUE;
}
BOOL CXLAutomation::StartExcel()
{
CLSID clsExcelApp;
// if Excel is already running, return with current instance
if (m_pdispExcelApp != NULL)
return TRUE;
/* Obtain the CLSID that identifies EXCEL.APPLICATION
* This value is universally unique to Excel versions 5 and up, and
* is used by OLE to identify which server to start. We are obtaining
* the CLSID from the ProgID.
*/
if (FAILED(CLSIDFromProgID(L"Excel.Application", &clsExcelApp)))
{
MessageBox(NULL, _T("Cannot obtain CLSID from ProgID"), "Failed", MB_OK | MB_ICONSTOP);
return FALSE;
}
// start a new copy of Excel, grab the IDispatch interface
if (FAILED(CoCreateInstance(clsExcelApp, NULL, CLSCTX_LOCAL_SERVER, IID_IDispatch, (void**)&m_pdispExcelApp)))
{
MessageBox(NULL, _T("Cannot start an instance of Excel for Automation."), "Failed", MB_OK | MB_ICONSTOP);
return FALSE;
}
return TRUE;
}
/*******************************************************************
*
* INVOKE
*
*******************************************************************/
/*
* INVOKE
*
* Invokes a method or property. Takes the IDispatch object on which to invoke,
* and the name of the method or property as a String. Arguments, if any,
* must have been previously setup using the AddArgumentXxx() functions.
*
* Returns TRUE if the call succeeded. Returns FALSE if an error occurred.
* A messagebox will be displayed explaining the error unless the DISP_NOSHOWEXCEPTIONS
* flag is specified. Errors can be a result of unrecognized method or property
* names, bad argument names, invalid types, or runtime-exceptions defined
* by the recipient of the Invoke.
*
* The argument list is reset via ClearAllArgs() if the DISP_FREEARGS flag is
* specified. If not specified, it is up to the caller to call ClearAllArgs().
*
* The return value is placed in pvargReturn, which is allocated by the caller.
* If no return value is required, pass NULL. It is up to the caller to free
* the return value (ReleaseVariant()).
*
* This function calls IDispatch::GetIDsOfNames for every invoke. This is not
* very efficient if the same method or property is invoked multiple times, since
* the DISPIDs for a particular method or property will remain the same during
* the lifetime of an IDispatch object. Modifications could be made to this code
* to cache DISPIDs. If the target application is always the same, a similar
* modification is to statically browse and store the DISPIDs at compile-time, since
* a given application will return the same DISPIDs in different sessions.
* Eliminating the extra cross-process GetIDsOfNames call can result in a
* signficant time savings.
*/
BOOL CXLAutomation::ExlInvoke(IDispatch *pdisp, LPOLESTR szMember, VARIANTARG * pvargReturn,
WORD wInvokeAction, WORD wFlags)
{
HRESULT hr;
DISPPARAMS dispparams;
unsigned int uiArgErr;
EXCEPINFO excep;
// Get the IDs for the member and its arguments. GetIDsOfNames expects the
// member name as the first name, followed by argument names (if any).
m_alpszArgNames[0] = szMember;
hr = pdisp->GetIDsOfNames( IID_NULL, m_alpszArgNames,
1 + m_iNamedArgCount, LOCALE_SYSTEM_DEFAULT, m_aDispIds);
if (FAILED(hr))
{
if (!(wFlags & DISP_NOSHOWEXCEPTIONS))
ShowException(szMember, hr, NULL, 0);
return FALSE;
}
if (pvargReturn != NULL)
ClearVariant(pvargReturn);
// if doing a property put(ref), we need to adjust the first argument to have a
// named arg of DISPID_PROPERTYPUT.
if (wInvokeAction & (DISPATCH_PROPERTYPUT | DISPATCH_PROPERTYPUTREF))
{
m_iNamedArgCount = 1;
m_aDispIds[1] = DISPID_PROPERTYPUT;
pvargReturn = NULL;
}
dispparams.rgdispidNamedArgs = m_aDispIds + 1;
dispparams.rgvarg = m_aVargs;
dispparams.cArgs = m_iArgCount;
dispparams.cNamedArgs = m_iNamedArgCount;
excep.pfnDeferredFillIn = NULL;
hr = pdisp->Invoke(m_aDispIds[0], IID_NULL, LOCALE_SYSTEM_DEFAULT,
wInvokeAction, &dispparams, pvargReturn, &excep, &uiArgErr);
if (wFlags & DISP_FREEARGS)
ClearAllArgs();
if (FAILED(hr))
{
// display the exception information if appropriate:
if (!(wFlags & DISP_NOSHOWEXCEPTIONS))
ShowException(szMember, hr, &excep, uiArgErr);
// free exception structure information
SysFreeString(excep.bstrSource);
SysFreeString(excep.bstrDescription);
SysFreeString(excep.bstrHelpFile);
return FALSE;
}
return TRUE;
}
/*
* ClearVariant
*
* Zeros a variant structure without regard to current contents
*/
void CXLAutomation::ClearVariant(VARIANTARG *pvarg)
{
pvarg->vt = VT_EMPTY;
pvarg->wReserved1 = 0;
pvarg->wReserved2 = 0;
pvarg->wReserved3 = 0;
pvarg->lVal = 0;
}
/*
* ClearAllArgs
*
* Clears the existing contents of the arg array in preparation for
* a new invocation. Frees argument memory if so marked.
*/
void CXLAutomation::ClearAllArgs()
{
int i;
for (i = 0; i < m_iArgCount; i++)
{
if (m_awFlags[i] & DISPARG_NOFREEVARIANT)
// free the variant's contents based on type
ClearVariant(&m_aVargs[i]);
else
//ClearVariant(&m_aVargs[i]);
ReleaseVariant(&m_aVargs[i]);
}
m_iArgCount = 0;
m_iNamedArgCount = 0;
}
void CXLAutomation::ReleaseVariant(VARIANTARG *pvarg)
{
VARTYPE vt;
VARIANTARG *pvargArray;
long lLBound, lUBound, l;
vt = pvarg->vt & 0xfff; // mask off flags
// check if an array. If so, free its contents, then the array itself.
if (V_ISARRAY(pvarg))
{
// variant arrays are all this routine currently knows about. Since a
// variant can contain anything (even other arrays), call ourselves
// recursively.
if (vt == VT_VARIANT)
{
SafeArrayGetLBound(pvarg->parray, 1, &lLBound);
SafeArrayGetUBound(pvarg->parray, 1, &lUBound);
if (lUBound > lLBound)
{
lUBound -= lLBound;
SafeArrayAccessData(pvarg->parray, (void**)&pvargArray);
for (l = 0; l < lUBound; l++)
{
ReleaseVariant(pvargArray);
pvargArray++;
}
SafeArrayUnaccessData(pvarg->parray);
}
}
else
{
return ;//1; // non-variant type
// MessageBox(NULL, _T("ReleaseVariant: Array contains non-variant type"), "Failed", MB_OK | MB_ICONSTOP);
}
// Free the array itself.
SafeArrayDestroy(pvarg->parray);
}
else
{
switch (vt)
{
case VT_DISPATCH:
//(*(pvarg->pdispVal->lpVtbl->Release))(pvarg->pdispVal);
pvarg->pdispVal->Release();
break;
case VT_BSTR:
SysFreeString(pvarg->bstrVal);
break;
case VT_I2:
case VT_BOOL:
case VT_R8:
case VT_ERROR: // to avoid erroring on an error return from Excel
// no work for these types
break;
default:
return;// 2; //unknonw type
// MessageBox(NULL, _T("ReleaseVariant: Unknown type"), "Failed", MB_OK | MB_ICONSTOP);
break;
}
}
ClearVariant(pvarg);
return ;//0;
}
BOOL CXLAutomation::SetExcelVisible(BOOL bVisible)
{
if (m_pdispExcelApp == NULL)
return FALSE;
ClearAllArgs();
AddArgumentBool(NULL, 0, bVisible);
return ExlInvoke(m_pdispExcelApp, L"Visible", NULL, DISPATCH_PROPERTYPUT, DISP_FREEARGS);
}
BOOL CXLAutomation::SetExcelFileValidation(BOOL bFileValidation)
{
if (m_pdispExcelApp == NULL)
return FALSE;
ClearAllArgs();
AddArgumentBool(NULL, 0, bFileValidation);
return ExlInvoke(m_pdispExcelApp, L"FileValidation", NULL, DISPATCH_PROPERTYPUT, DISP_FREEARGS);
}
/*******************************************************************
*
* ARGUMENT CONSTRUCTOR FUNCTIONS
*
* Each function adds a single argument of a specific type to the list
* of arguments for the current invoke. If appropriate, memory may be
* allocated to represent the argument. This memory will be
* automatically freed the next time ClearAllArgs() is called unless
* the NOFREEVARIANT flag is specified for a particular argument. If
* NOFREEVARIANT is specified it is the responsibility of the caller
* to free the memory allocated for or contained within the argument.
*
* Arguments may be named. The name string must be a C-style string
* and it is owned by the caller. If dynamically allocated, the caller
* must free the name string.
*
*******************************************************************/
/*
* Common code used by all variant types for setting up an argument.
*/
void CXLAutomation::AddArgumentCommon(LPOLESTR lpszArgName, WORD wFlags, VARTYPE vt)
{
ClearVariant(&m_aVargs[m_iArgCount]);
m_aVargs[m_iArgCount].vt = vt;
m_awFlags[m_iArgCount] = wFlags;
if (lpszArgName != NULL)
{
m_alpszArgNames[m_iNamedArgCount + 1] = lpszArgName;
m_iNamedArgCount++;
}
}
BOOL CXLAutomation::AddArgumentDispatch(LPOLESTR lpszArgName, WORD wFlags, IDispatch * pdisp)
{
AddArgumentCommon(lpszArgName, wFlags, VT_DISPATCH);
m_aVargs[m_iArgCount++].pdispVal = pdisp;
return TRUE;
}
BOOL CXLAutomation::AddArgumentInt2(LPOLESTR lpszArgName, WORD wFlags, int i)
{
AddArgumentCommon(lpszArgName, wFlags, VT_I2);
m_aVargs[m_iArgCount++].iVal = i;
return TRUE;
}
BOOL CXLAutomation::AddArgumentBool(LPOLESTR lpszArgName, WORD wFlags, BOOL b)
{
AddArgumentCommon(lpszArgName, wFlags, VT_BOOL);
// Note the variant representation of True as -1
m_aVargs[m_iArgCount++].boolVal = b ? -1 : 0;
return TRUE;
}
BOOL CXLAutomation::AddArgumentDouble(LPOLESTR lpszArgName, WORD wFlags, double d)
{
AddArgumentCommon(lpszArgName, wFlags, VT_R8);
m_aVargs[m_iArgCount++].dblVal = d;
return TRUE;
}
BOOL CXLAutomation::ReleaseExcel()
{
if (m_pdispExcelApp == NULL)
return TRUE;
// Tell Excel to quit, since for automation simply releasing the IDispatch
// object isn't enough to get the server to shut down.
// Note that this code will hang if Excel tries to display any message boxes.
// This can occur if a document is in need of saving. The CreateChart() code
// always clears the dirty bit on the documents it creates, avoiding this problem.
ClearAllArgs();
ExlInvoke(m_pdispExcelApp, L"Quit", NULL, DISPATCH_METHOD, 0);
// Even though Excel has been told to Quit, we still need to release the
// OLE object to account for all memory.
ReleaseDispatch();
return TRUE;
}
//Create an empty workshet
BOOL CXLAutomation::CreateWorkSheet()
{
if(NULL == m_pdispExcelApp)
return FALSE;
BOOL fResult;
VARIANTARG varg1, varg2;
IDispatch *pdispRange = NULL;
IDispatch *pdispActiveSheet = NULL;
IDispatch *pdispActiveCell = NULL;
IDispatch *pdispCrt = NULL;
// Set wb = [application].Workbooks.Add(template := xlWorksheet)
ClearAllArgs();
if (!ExlInvoke(m_pdispExcelApp, L"Workbooks", &varg1, DISPATCH_PROPERTYGET, 0))
return FALSE;
ClearAllArgs();
AddArgumentInt2(L"Template", 0, xlWorksheet);
fResult = ExlInvoke(varg1.pdispVal, L"Add", &varg2, DISPATCH_METHOD, 0);
ReleaseVariant(&varg1);
if (!fResult)
return FALSE;
m_pdispWorkbook = varg2.pdispVal;
// Set ws = wb.Worksheets(1)
ClearAllArgs();
AddArgumentInt2(NULL, 0, 1);
if (!ExlInvoke(m_pdispWorkbook, L"Worksheets", &varg2, DISPATCH_PROPERTYGET, 0))
goto CreateWsBail;
m_pdispWorksheet = varg2.pdispVal;
fResult = TRUE;
CreateWsExit:
if (pdispRange != NULL)
pdispRange->Release();
if (pdispCrt != NULL)
pdispCrt->Release();
return fResult;
CreateWsBail:
fResult = FALSE;
goto CreateWsExit;
}
/*
* OLE and IDispatch use a BSTR as the representation of strings.
* This constructor automatically copies the passed-in C-style string
* into a BSTR. It is important to not set the NOFREEVARIANT flag
* for this function, otherwise the allocated BSTR copy will probably
* get lost and cause a memory leak.
*/
BOOL CXLAutomation::AddArgumentOLEString(LPOLESTR lpszArgName, WORD wFlags, LPOLESTR lpsz)
{
BSTR b;
b = SysAllocString(lpsz);
if (!b)
return FALSE;
AddArgumentCommon(lpszArgName, wFlags, VT_BSTR);
m_aVargs[m_iArgCount++].bstrVal = b;
return TRUE;
}
BOOL CXLAutomation::AddArgumentCString(LPOLESTR lpszArgName, WORD wFlags, CString szStr)
{
BSTR b;
b = szStr.AllocSysString();
if (!b)
return FALSE;
AddArgumentCommon(lpszArgName, wFlags, VT_BSTR);
m_aVargs[m_iArgCount++].bstrVal = b;
return TRUE;
}
/*
* Constructs an 1-dimensional array containing variant strings. The strings
* are copied from an incoming array of C-Strings.
*/
BOOL CXLAutomation::AddArgumentCStringArray(LPOLESTR lpszArgName, WORD wFlags, LPOLESTR *paszStrings, int iCount)
{
SAFEARRAY *psa;
SAFEARRAYBOUND saBound;
VARIANTARG *pvargBase;
VARIANTARG *pvarg;
int i, j;
saBound.lLbound = 0;
saBound.cElements = iCount;
psa = SafeArrayCreate(VT_VARIANT, 1, &saBound);
if (psa == NULL)
return FALSE;
SafeArrayAccessData(psa, (void**) &pvargBase);
pvarg = pvargBase;
for (i = 0; i < iCount; i++)
{
// copy each string in the list of strings
ClearVariant(pvarg);
pvarg->vt = VT_BSTR;
if ((pvarg->bstrVal = SysAllocString(*paszStrings++)) == NULL)
{
// memory failure: back out and free strings alloc'ed up to
// now, and then the array itself.
pvarg = pvargBase;
for (j = 0; j < i; j++)
{
SysFreeString(pvarg->bstrVal);
pvarg++;
}
SafeArrayDestroy(psa);
return FALSE;
}
pvarg++;
}
SafeArrayUnaccessData(psa);
// With all memory allocated, setup this argument
AddArgumentCommon(lpszArgName, wFlags, VT_VARIANT | VT_ARRAY);
m_aVargs[m_iArgCount++].parray = psa;
return TRUE;
}
//Clean up: release dipatches
void CXLAutomation::ReleaseDispatch()
{
if(NULL != m_pdispExcelApp)
{
m_pdispExcelApp->Release();
m_pdispExcelApp = NULL;
}
if(NULL != m_pdispWorksheet)
{
m_pdispWorksheet->Release();
m_pdispWorksheet = NULL;
}
if(NULL != m_pdispWorkbook)
{
m_pdispWorkbook->Release();
m_pdispWorkbook = NULL;
}
if(NULL != m_pdispActiveChart)
{
m_pdispActiveChart->Release();
m_pdispActiveChart = NULL;
}
}
void CXLAutomation::ShowException(LPOLESTR szMember, HRESULT hr, EXCEPINFO *pexcep, unsigned int uiArgErr)
{
TCHAR szBuf[512];
switch (GetScode(hr))
{
case DISP_E_UNKNOWNNAME:
wsprintf(szBuf, "%s: Unknown name or named argument.", szMember);
break;
case DISP_E_BADPARAMCOUNT:
wsprintf(szBuf, "%s: Incorrect number of arguments.", szMember);
break;
case DISP_E_EXCEPTION:
wsprintf(szBuf, "%s: Error %d: ", szMember, pexcep->wCode);
if (pexcep->bstrDescription != NULL)
lstrcat(szBuf, (char*)pexcep->bstrDescription);
else
lstrcat(szBuf, "<<No Description>>");
break;
case DISP_E_MEMBERNOTFOUND:
wsprintf(szBuf, "%s: method or property not found.", szMember);
break;
case DISP_E_OVERFLOW:
wsprintf(szBuf, "%s: Overflow while coercing argument values.", szMember);
break;
case DISP_E_NONAMEDARGS:
wsprintf(szBuf, "%s: Object implementation does not support named arguments.",
szMember);
break;
case DISP_E_UNKNOWNLCID:
wsprintf(szBuf, "%s: The locale ID is unknown.", szMember);
break;
case DISP_E_PARAMNOTOPTIONAL:
wsprintf(szBuf, "%s: Missing a required parameter.", szMember);
break;
case DISP_E_PARAMNOTFOUND:
wsprintf(szBuf, "%s: Argument not found, argument %d.", szMember, uiArgErr);
break;
case DISP_E_TYPEMISMATCH:
wsprintf(szBuf, "%s: Type mismatch, argument %d.", szMember, uiArgErr);
break;
default:
wsprintf(szBuf, "%s: Unknown error occured.", szMember);
break;
}
MessageBox(NULL, szBuf, "OLE Error", MB_OK | MB_ICONSTOP);
}
//Open Microsoft Excel file and switch to the firs available worksheet.
BOOL CXLAutomation::OpenExcelFile(CString szFileName)
{
//Leave if the file cannot be open
if(NULL == m_pdispExcelApp)
return FALSE;
if(szFileName.IsEmpty())
return FALSE;
VARIANTARG varg1, vargWorkbook, vargWorksheet;
SetExcelFileValidation(FALSE);
ClearAllArgs();
if (!ExlInvoke(m_pdispExcelApp, L"Workbooks", &varg1, DISPATCH_PROPERTYGET, 0))
return FALSE;
ClearAllArgs();
AddArgumentCString(L"Filename", 0, szFileName);
if (!ExlInvoke(varg1.pdispVal, L"Open", &vargWorkbook, DISPATCH_PROPERTYGET, DISP_FREEARGS))
return FALSE;
//Now let's get the first worksheet of this workbook
ClearAllArgs();
AddArgumentInt2(NULL, 0, 1);
if (!ExlInvoke(vargWorkbook.pdispVal, L"Worksheets", &vargWorksheet, DISPATCH_PROPERTYGET, DISP_FREEARGS))
return FALSE;
//Close the empty worksheet
ClearAllArgs();
//if (!ExlInvoke(m_pdispWorkbook, L"Close", NULL, DISPATCH_PROPERTYGET, DISP_FREEARGS))
// return FALSE;
SetExcelVisible(TRUE);
//Remember the newly open worksheet
m_pdispWorkbook = vargWorkbook.pdispVal;
m_pdispWorksheet = vargWorksheet.pdispVal;
ReleaseDispatch();
return TRUE;
}
At first glance it seems your pvarg may not be fully consistent / not providing what's expected. The clear function does no checks, so it will just write, regardless. Or try to.
But that may be a gross oversimplification without a full and thorough look at all involved code.
Adding this here as your project is closed on Freelancer and who knows, it may help you or another think in the right direction at a future date anyway.
I fixed the problem by not using that MS class library at all - it is way too complicated and prone to problems.
I found a simple code sample here and adapted it for my needs.
I have added code to open the Excel file as I need to, here is the source which I hope will help anyone with a similar problem.
Whoever down voted the question - please reconsider and vote it back up.
// Start server and get IDispatch...
IDispatch *pXlApp;
hr = CoCreateInstance(clsid, NULL, CLSCTX_LOCAL_SERVER, IID_IDispatch, (void **)&pXlApp);
if(FAILED(hr)) {
::MessageBox(NULL, "Excel not registered properly", "Error", 0x10010);
return -2;
}
// Make it visible (i.e. app.visible = 1)
{
VARIANT x;
x.vt = VT_I4;
x.lVal = 1;
AutoWrap(DISPATCH_PROPERTYPUT, NULL, pXlApp, L"Visible", 1, x);
}
// Get Workbooks collection
IDispatch *pXlBooks;
{
VARIANT result;
VariantInit(&result);
AutoWrap(DISPATCH_PROPERTYGET, &result, pXlApp, L"Workbooks", 0);
pXlBooks = result.pdispVal;
}
// Open Excel file
{
VARIANT result;
VariantInit(&result);
VARIANT fname;
fname.vt = VT_BSTR;
std::string str = GetAppPath() + "\\test.xlsm";
fname.bstrVal=::SysAllocString(CA2W (str.c_str ()));
AutoWrap(DISPATCH_METHOD, &result, pXlBooks, L"Open", 1, fname);
}
// Release references...
pXlBooks->Release();
pXlApp->Release();
I've built a list and inserted labels in each cell. For now the text that is too long simply disappear. I'd like to wrap the text so it is entirely visible inside each cell.
Can you please help?
update: issue solved
For those who need an answer, I used LWUIT's HTMLComponent inside a container. The HTMLComponent allows you to use HTML code. That would allow you to format your list the way you want it to be.
Here is more details on the solution.
In Java ME with LWUIT, I used a HTMLComponent to get the precise layout I wanted. The best way for me was to use an HTML Table inside the HTMLComponent. It just behaves like HTML.
String html_code = "";
html_code = "<table width='100%'>";
html_code += "<tr><td><strong>"+fullname+"</strong></td></tr>";
if (title.length()>0) { html_code += "<tr><td><i>"+title+"</i></td></tr>"; }
if (message.length()>0) { html_code += "<tr><td>"+message+"</td></tr>"; }
if (date.length()>0) { html_code += "<tr><td><i>"+date+"</i></td></tr>"; }
html_code += "</table>";
HTMLComponent html = new HTMLComponent(null);
html.setBodyText(html_code);
Just incase if you are looking for a more "elegant" solution, i found a handy resource online. I am posting here for reference purposes, but HtmlComponent does the job.
import com.sun.lwuit.Font;
/** A class supporting word wrap for MIDP. */
public class WordWrap {
Font font;
int width;
String txt;
int pos;
/**
* Initializes the WordWrap object with the given Font, the text string
* to be wrapped, and the target width.
*
* #param font: The Font to be used to calculate the character widths.
* #param txt: The text string to be wrapped.
* #param width: The line width.
*/
public WordWrap (Font font, String txt, int width) {
this.font = font;
this.txt = txt;
this.width = width;
}
/**
* returns the next line break position. If no text is left, -1 is returned.
*/
public int next () {
int i = pos;
int len = txt.length ();
if (pos >= len) return -1;
int start = pos;
while (true) {
while (i < len && txt.charAt (i) > ' ')
i++;
int w = font.stringWidth (txt.substring (start, i));
if (pos == start) {
if (w > width) {
while (font.stringWidth (txt.substring (start, --i)) > width)
{ }
pos = i;
break;
}
}
if (w <= width) pos = i;
if (w > width || i >= len || txt.charAt(i) == '\n') break;
i++;
}
return pos >= len ? pos : ++pos;
}
}
import com.sun.lwuit.Button;
import com.sun.lwuit.Component;
import com.sun.lwuit.Container;
import com.sun.lwuit.Display;
import com.sun.lwuit.Label;
import com.sun.lwuit.events.ActionListener;
import com.sun.lwuit.events.FocusListener;
import com.sun.lwuit.geom.Dimension;
import com.sun.lwuit.layouts.BoxLayout;
import com.sun.lwuit.plaf.Border;
import com.sun.lwuit.plaf.Style;
/**
*
* #author rubycube
*/
public class WrapList extends Container {
private Button hiddenButton;
private int id;
public WrapList(String text, int containerID) {
id = containerID;
this.setLayout(new BoxLayout(BoxLayout.Y_AXIS));
this.setFocusable(false);
final Style thisContainerStyle = this.getStyle();
Border thisContainerBorder = Border.createRoundBorder(20, 20, 0xcccccc);
thisContainerStyle.setBorder(thisContainerBorder);
hiddenButton = new Button(" ");
hiddenButton.setPreferredSize(new Dimension(1, 1));
Style style = hiddenButton.getStyle();
style.setBgTransparency(0, false);
style.setBorder(Border.createEmpty());
FocusListener hiddenButtonFL = new FocusListener() {
public void focusGained(Component cmp) {
WrapList parentContainer = ((WrapList) (cmp.getParent()));
Border parentContainerBorder = Border.createRoundBorder(20, 20, 0xff6600);
Style parentContainerStyle = parentContainer.getStyle();
parentContainerStyle.setBorder(parentContainerBorder);
parentContainerStyle.setBgColor(0xff9900);
parentContainerStyle.setBgTransparency(50);
parentContainer.repaint();
}
public void focusLost(Component cmp) {
WrapList parentContainer = ((WrapList) (cmp.getParent()));
Border parentContainerBorder = Border.createRoundBorder(20, 20, 0xcccccc);
Style parentContainerStyle = parentContainer.getStyle();
parentContainerStyle.setBorder(parentContainerBorder);
parentContainerStyle.setBgTransparency(0);
parentContainer.repaint();
}
};
hiddenButton.addFocusListener(hiddenButtonFL);
Label l = new Label(text);
l.setSelectedStyle(thisContainerStyle);
//l.setUnselectedStyle(thisContainerStyle);
WordWrap ww = new WordWrap(l.getStyle().getFont(), text, (Display.getInstance().getDisplayWidth() - 10));
int si = 0;
int ei = 0;
while (true) {
int np = ww.next();
if (np == -1) {
break;
} else {
si = ei;
ei = np;
}
String lineText = text.substring(si, ei);
Label line = new Label(lineText);
line.setEndsWith3Points(false);
this.addComponent(line);
}
this.addComponent(hiddenButton);
}
public void addActionListener(ActionListener actionlistener) {
hiddenButton.addActionListener(actionlistener);
}
/**
* #return the id
*/
public int getId() {
return id;
}
/**
* #param id the id to set
*/
public void setId(int id) {
this.id = id;
}
}