If you have a cool piece of software to share, but you are not hosting it officially yet, please dump it in here. If you have code snippets that are useful, please donate!
Jorg just suggested to place this peace of code here - and I obey
I inserted the attached code into the grid-sample and it's supposed to copy / paste data from or to MS-Excel.
The basic thing is, that in Excel the clipboard data seperates the fields within one line with tabs, the lines (no wonder) with a linefeed.
I did all things manually - OK, there may be a better solution (more automatic or without my "GetSelectedRows()" problem), but this solution works. Use it where appropriate.
#include <wx/clipbrd.h>
void GridFrame::CopyData( wxCommandEvent& WXUNUSED(ev) )
{
int i,k;
wxString copy_data;
bool something_in_this_line;
copy_data.Clear();
for (i=0; i<grid->GetRows(); i++) { // step through all lines
something_in_this_line = false; // nothing found yet
for (k=0; k<grid->GetCols(); k++) { // step through all colums
if (grid->IsInSelection(i,k)) { // this field is selected!!!
if (something_in_this_line == false) { // first field in this line => may need a linefeed
if (copy_data.IsEmpty() == false) { // ... if it is not the very first field
copy_data = copy_data + wxT("\n"); // next LINE
}
something_in_this_line = true;
} else { // if not the first field in this line we need a field seperator (TAB)
copy_data = copy_data + wxT("\t"); // next COLUMN
}
copy_data = copy_data + grid->GetCellValue(i,k); // finally we need the field value :-)
}
}
}
/* I tried this, but it DID NOT WORK!!!!
wxArrayInt row_index, col_index;
row_index = grid->GetSelectedRows(); // the ARRAYS were EMPTY!!! Don't know why!
col_index = grid->GetSelectedCols();
for (i=0; i<row_index.GetCount(); i++) {
if (i > 0) {
copy_data = copy_data + wxT("\n"); // next ROW
}
for (k=0; k<col_index.GetCount(); k++) {
if (k > 0) {
copy_data = copy_data + wxT("\t"); // next COLUMN
}
copy_data = copy_data + grid->GetCellValue(row_index[i],col_index[k]);
}
}
*/
wxOpenClipboard(); // now copy all these things into the clipbord
wxEmptyClipboard();
wxSetClipboardData(wxDF_TEXT,copy_data.c_str(),0,0);
wxCloseClipboard();
}
void GridFrame::PasteData( wxCommandEvent& WXUNUSED(ev) )
{
wxString copy_data;
wxString cur_field;
wxString cur_line;
int i,k,k2;
wxOpenClipboard(); // now copy all these things into the clipbord
copy_data = (char *)wxGetClipboardData(wxDF_TEXT);
wxCloseClipboard();
// I admit, the string contains all fields from min-selection to max selection,
// even if rows or columns inbetween are NOT selected
// Don't know if this is an EXCEL or WX problem!
// But as the same thing happenes in Word, I think, it's Bills fault!
// i = 0; k = 0; // Where to insert - 0,0 or left/top current cursor position
i = grid->GetGridCursorRow();
k = grid->GetGridCursorCol();
k2= k;
do {
cur_line = copy_data.BeforeFirst('\n');
copy_data = copy_data.AfterFirst('\n');
do {
cur_field = cur_line.BeforeFirst('\t');
cur_line = cur_line.AfterFirst ('\t');
grid->SetCellValue(i,k,cur_field);
k++;
} while(cur_line.IsEmpty() == false);
i++;
k = k2;
} while (copy_data.IsEmpty() == false);
}
I was trying to use this code in my project and found that it is extremely slow when copying large grids (100 x 2000). If you replace all the lines like these:
copy_data = copy_data + wxT("\t"); // next COLUMN
with
copy_data.Append(wxT("\t"));
it is much faster.
Seems .Append on a string is faster than = itself + other string.
my_grid = new wxGrid(my_panel, -1, wxPoint(0, 0), wxSize(300, 300));
//connect the grid to the key event handler to provide Ctrl+C and Ctrl+V
my_grid->Connect(wxID_ANY,
wxEVT_KEY_DOWN,
wxKeyEventHandler(my_frame::CopyPasteData),
(wxObject*) NULL,
this);
void my_frame::CopyPasteData(wxKeyEvent& event) {
if ((event.GetUnicodeKey() == 'C') && (event.ControlDown() == true)) {
//put all the copy functionality here
} else if ((event.GetUnicodeKey() == 'V') && (event.ControlDown() == true)) {
//put all the paste functionality here
}
event.Skip();
}
I've got a little problem. At first i 'd say that i'm really at the first stemps with C++ and some thinghs are quite confused expecially where write some parts of the declaration code.
In this case i use the functions written above and they runs.
The problem is with the "GetUnicodeKey"
The compiler says that : "class wxKeyEvent has no member called 'GetUnicodeKey'"
In the wxUserGuide I found:
wxKeyEvent::GetUnicodeKey
wxChar GetUnicodeKey() const
Returns the Unicode character corresponding to this key event.
This function is only available in Unicode build, i.e. when wxUSE_UNICODE is 1.
Ok... I don't understand where is supposed to be declared wxUSE_UNICODE == 1
It should not be use by default settings???
do I have to define it in someway????
another questions just we are uin theme:
when you write for example: for (int j=0; j<GetCols(); j++)
the compiler sand me an error... i solved this writing for (int j=0; j<grid->GetCols(); j++) //grid is the pointer to mywxGrid
in fact how could it understand which is the object it has to GetCols if I don't specifies a pointer????
Thanks in advance and sorry if my English is not perfect.
MarcoC++ wrote:This function is only available in Unicode build, i.e. when wxUSE_UNICODE is 1.
Ok... I don't understand where is supposed to be declared wxUSE_UNICODE == 1
It should not be use by default settings???
do I have to define it in someway????
You have to define if you want to use Unicode or not before compiling wyWidgets. How exactly you do that depends on the Software you use to compile wxWidgets.
/******************************************************************************/
void myGrid::Copy(wxCommandEvent &event)
{
wxString copy_data;
bool something_in_this_line;
copy_data.Clear();
for (int i=0; i<GetRows();i++)
{
something_in_this_line = false;
for (int j=0; j<GetCols(); j++)
{
if (IsInSelection(i,j))
{
if (something_in_this_line == false)
{
if (copy_data.IsEmpty() == false)
{
copy_data.Append(wxT("\r\n")); // in windows if copy to notepad need \r\n to newline
}
something_in_this_line = true;
}
else
{
copy_data.Append(wxT("\t"));
}
copy_data = copy_data + GetCellValue(i,j);
}
}
}
wxOpenClipboard();
wxEmptyClipboard();
wxSetClipboardData(wxDF_TEXT,copy_data.mb_str(),0,0); // in Windows , the need this for UNICODE
wxCloseClipboard();
}
/******************************************************************************/
if (wxTheClipboard->Open())
{
if (wxTheClipboard->IsSupported( wxDF_TEXT ))
{
wxTextDataObject data;
wxTheClipboard->GetData( data );
copy_data = data.GetText();
}
wxTheClipboard->Close();
}
Other things are broken in Sergio code since lot has changed. Below is edited code with syntax changes. Note that I have not used as is so there might be other things to correct :