How to sort tree view on click on column header - gtk

I am having a GtkTreeView with GtkTreeStore in it and I want to Sort this entire table (GtkTreeView) when user clicks on any of the column headers I also want to align text in the cells to left side.
How to do this?

Enjoy!
#! /usr/bin/python
###########################################################
#
# Basic Gtk.TreeView Example with two sortable columns
#
###########################################################
# use the new PyGObject binding
from gi.repository import Gtk
import os
import getpass # this is only to automatically print your home folder.
class MyWindow(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self, title='My Window Title')
self.connect('delete-event', Gtk.main_quit)
# Gtk.ListStore will hold data for the TreeView
# Only the first two columns will be displayed
# The third one is for sorting file sizes as numbers
store = Gtk.ListStore(str, str, long)
# Get the data - see below
self.populate_store(store)
treeview = Gtk.TreeView(model=store)
# The first TreeView column displays the data from
# the first ListStore column (text=0), which contains
# file names
renderer_1 = Gtk.CellRendererText()
column_1 = Gtk.TreeViewColumn('File Name', renderer_1, text=0)
# Calling set_sort_column_id makes the treeViewColumn sortable
# by clicking on its header. The column is sorted by
# the ListStore column index passed to it
# (in this case 0 - the first ListStore column)
column_1.set_sort_column_id(0)
treeview.append_column(column_1)
# xalign=1 right-aligns the file sizes in the second column
renderer_2 = Gtk.CellRendererText(xalign=1)
# text=1 pulls the data from the second ListStore column
# which contains filesizes in bytes formatted as strings
# with thousand separators
column_2 = Gtk.TreeViewColumn('Size in bytes', renderer_2, text=1)
# Make the Treeview column sortable by the third ListStore column
# which contains the actual file sizes
column_2.set_sort_column_id(1)
treeview.append_column(column_2)
# Use ScrolledWindow to make the TreeView scrollable
# Otherwise the TreeView would expand to show all items
# Only allow vertical scrollbar
scrolled_window = Gtk.ScrolledWindow()
scrolled_window.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC)
scrolled_window.add(treeview)
scrolled_window.set_min_content_height(200)
self.add(scrolled_window)
self.show_all()
def populate_store(self, store):
directory = '/home/'+getpass.getuser()
for filename in os.listdir(directory):
size = os.path.getsize(os.path.join(directory, filename))
# the second element is displayed in the second TreeView column
# but that column is sorted by the third element
# so the file sizes are sorted as numbers, not as strings
store.append([filename, '{0:,}'.format(size), size])
# The main part:
win = MyWindow()
Gtk.main()

In order:
You really need to start looking more at the fine documentation.
Make sure you set a sort column id on each of your columns, then look at the GtkTreeSortable interface. This tutorial section is helpful, too.
Set the "xalign" property of your GtkCellRenderer to 0.f.

Related

How to strip extra spaces when writing from dataframe to csv

Read in multiple sheets (6) from an xlsx file and created individual dataframes. Want to write each one out to a pipe delimited csv.
ind_dim.to_csv (r'/mypath/ind_dim_out.csv', index = None, header=True, sep='|')
Currently outputs like this:
1|value1 |value2 |word1 word2 word3 etc.
Want to strip trailing blanks
Suggestion
Include the method .apply(lambda x: x.str.rstrip()) to your output string (prior to the .to_csv() call) to strip the right trailing blank from each field across the DataFrame. It would look like:
Change:
ind_dim.to_csv(r'/mypath/ind_dim_out.csv', index = None, header=True, sep='|')
To:
ind_dim.apply(lambda x: x.str.rstrip()).to_csv(r'/mypath/ind_dim_out.csv', index = None, header=True, sep='|')
It can be easily inserted to the output code string using '.' referencing. To handle multiple data types, we can enforce the 'object' dtype on import by including the argument dtype='str':
ind_dim = pd.read_excel('testing_xlsx_nums.xlsx', header=0, index_col=0, sheet_name=None, dtype='str')
Or on the DataFrame itself by:
df = pd.DataFrame(df, dtype='str')
Proof
I did a mock-up where the .xlsx document has 5 sheets, with each sheet having three columns: The first column with all numbers except an empty cell in row 2; the second column with both a leading blank and a trailing blank on strings, an empty cell in row 3, and a number in row 4; and the third column * with all strings having a leading blank, and an empty value in row 4*. Integer indexes and integer columns have been included. The text in each sheet is:
0 1 2
0 11111 valueB1 valueC1
1 valueB2 valueC2
2 33333 valueC3
3 44444 44444
4 55555 valueB5 valueC5
This code reads in our .xlsx testing_xlsx_dtype.xlsx to the DataFrame dictionary ind_dim.
Next, it loops through each sheet using a for loop to place the sheet name variable as a key to reference the individual sheet DataFrame. It applies the .str.rstrip() method to the entire sheet/DataFrame by passing the lambda x: x.str.rstrip() lambda function to the .apply() method called on the sheet/DataFrame.
Finally, it outputs the sheet/DataFrame as a .csv with the pipe delimiter using .to_csv() as seen in the OP post.
# reads xlsx in
ind_dim = pd.read_excel('testing_xlsx_nums.xlsx', header=0, index_col=0, sheet_name=None, dtype='str')
# loops through sheets, applies rstrip(), output as csv '|' delimit
for sheet in ind_dim:
ind_dim[sheet].apply(lambda x: x.str.rstrip()).to_csv(sheet + '_ind_dim_out.csv', sep='|')
Returns:
|0|1|2
0|11111| valueB1| valueC1
1|| valueB2| valueC2
2|33333|| valueC3
3|44444|44444|
4|55555| valueB5| valueC5
(Note our column 2 strings no longer have the trailing space).
We can also reference each sheet using a loop that cycles through the dictionary items; the syntax would look like for k, v in dict.items() where k and v are the key and value:
# reads xlsx in
ind_dim = pd.read_excel('testing_xlsx_nums.xlsx', header=0, index_col=0, sheet_name=None, dtype='str')
# loops through sheets, applies rstrip(), output as csv '|' delimit
for k, v in ind_dim.items():
v.apply(lambda x: x.str.rstrip()).to_csv(k + '_ind_dim_out.csv', sep='|')
Notes:
We'll still need to apply the correct arguments for selecting/ignoring indexes and columns with the header= and names= parameters as needed. For these examples I just passed =None for simplicity.
The other methods that strip leading and leading & trailing spaces are: .str.lstrip() and .str.strip() respectively. They can also be applied to an entire DataFrame using the .apply(lambda x: x.str.strip()) lambda function passed to the .apply() method called on the DataFrame.
Only 1 Column: If we only wanted to strip from one column, we can call the .str methods directly on the column itself. For example, to strip leading & trailing spaces from a column named column2 in DataFrame df we would write: df.column2.str.strip().
Data types not string: When importing our data, pandas will assume data types for columns with a similar data type. We can override this by passing dtype='str' to the pd.read_excel() call when importing.
pandas 1.0.1 documentation (04/30/2020) on pandas.read_excel:
"dtypeType name or dict of column -> type, default None
Data type for data or columns. E.g. {‘a’: np.float64, ‘b’: np.int32} Use object to preserve data as stored in Excel and not interpret dtype. If converters are specified, they will be applied INSTEAD of dtype conversion."
We can pass the argument dtype='str' when importing with pd.read_excel.() (as seen above). If we want to enforce a single data type on a DataFrame we are working with, we can set it equal to itself and pass it to pd.DataFrame() with the argument dtype='str like: df = pd.DataFrame(df, dtype='str')
Hope it helps!
The following trims left and right spaces fairly easily:
if (!require(dplyr)) {
install.packages("dplyr")
}
library(dplyr)
if (!require(stringr)) {
install.packages("stringr")
}
library(stringr)
setwd("~/wherever/you/need/to/get/data")
outputWithSpaces <- read.csv("CSVSpace.csv", header = FALSE)
print(head(outputWithSpaces), quote=TRUE)
#str_trim(string, side = c("both", "left", "right"))
outputWithoutSpaces <- outputWithSpaces %>% mutate_all(str_trim)
print(head(outputWithoutSpaces), quote=TRUE)
Starting Data:
V1 V2 V3 V4
1 "Something is interesting. " "This is also Interesting. " "Not " "Intereting "
2 " Something with leading space" " Leading" " Spaces with many words." " More."
3 " Leading and training Space. " " More " " Leading and trailing. " " Spaces. "
Resulting:
V1 V2 V3 V4
1 "Something is interesting." "This is also Interesting." "Not" "Intereting"
2 "Something with leading space" "Leading" "Spaces with many words." "More."
3 "Leading and training Space." "More" "Leading and trailing." "Spaces."

array values and print specified number of characters

I have a variable which contains a list of contents as an array.
$procs = #{name="explorer",type="svchost"}
How do I access the value of first element (i.e. explorer) from the array and store into a variable?
And then print the first three letters of that value (i.e. exp)?
# for the first tree letters of the first hash table value
$NewVar = (#($procs.Values)[0]).Substring(0,3)
# for the first tree letters of a specific hash table element (name)
$NewVar = ($procs.name).Substring(0,3)

MS Word: select text inside a table cell

I need to select a text (for example, two chars) inside a cell in a table in a Word document. The following code:
Sub testTable()
For Each itable In ActiveDocument.Tables
itable.Cell(1, 2).Range.Select
Next
End Sub
selects all the content of the second cell in the first row of the table. How have I to modify it to select only a subset of the cell content, for example from the 4th char to the 9th char?
The Range object has a Characters property, so:
itable.Cell(1,2).Range.Characters(4).Select
Selection.MoveEnd wdCharacter, 5
Another way to go about it is to work with Range objects:
Dim rng as Word.Range
Set rng = itable.Cell(1,2).Range.Characters(4)
rng.End = itable.Cell(1,2).Range.Characters(9)
And there are variations on the theme...

Cannot read from an xls file (MATLAB)

I'm trying to read data from a xls file using
[a,b,c]=xlsread('list.xls', 1, 'A1:C5')
but as the result I get all a, b and c empty, even though there is data in the list.xls spreadsheet at the specified range. What might be the problem?
From http://www.mathworks.com/help/matlab/ref/xlsread.html:
[num,txt,raw] = xlsread(___)
additionally returns the text fields in cell array txt, and the
unprocessed data (numbers and text) in cell array raw using any of the
input arguments in the previous syntaxes. If xlRange is specified,
leading blank rows and columns in the worksheet that precede rows and
columns with data are returned in raw.
If you are only interested in data (numbers), you may type
xlsread(filename,1,'A1:C5')
If you have headers on the first row, call
[num,txt,raw] = xlsread(___)
num: array containing data;
txt: cell containing headers;
raw: cell containing headers and data.
I hope this helps

Matlab: finding/writing data from mutliple files by column header text

I have an array which I read into Matlab with importdata. It has 5 header lines
file = 'aoao.csv';
s = importdata(file,',', 5);
Matlab automatically treats the last line as the column header. I can then call up the column number that I want with
s.data(:,n); %n is desired column number
I want to be able to load up many similar files at once, and then call up the columns in the different files which have the same column header name (which are not necessarily the same column number). I want to be able to write and export all of these columns together into a new matrix, preferably with each column labelled with its file name,
what should I do?
samp = 'len-c.mp3'; %# define desired sample/column header name
file = dir('*.csv');
have the directory ready in main screen current folder. This creates a detailed description of file,
for i=1:length(file)
set(i) = importdata(file(i).name,',', 5);
end
this imports the data from each of the files (comma delimited, 5 header lines) and transports it to a cell array called 'set'
for k = 1:14;
for i=1:length(set(k).colheaders)
TF = strcmp(set(k).colheaders(i),samp); %compares strings for match
if TF == 1; %if match is true
group(:,k) = set(k).data(:,i); %save matching column# to 'group'
end
end
end
this retrieves the data from the named colheader within each file