I am trying to replace the values in the first 4 rows of a attribute table with the row values from the next 4 rows 5:8 in an attribute table using arcpy.da.UpdateCursor. Is there a simple way to index rows 1:4 (all columns) and replace with values from rows 5:8.
Here is my code thus far:
targetFC = r"D:\ZOC\POLYPGDIS_MASTER_1.shp"
dsc = arcpy.Describe(sourceFC)
fields = dsc.fields
# List all field names except the OID field
fieldnames = [field.name for field in fields if field.name != dsc.OIDFieldName]
with arcpy.da.UpdateCursor(targetFC, fieldnames) as cursor:
for row in cursor:
row[1:4] = row[5:8]
cursor.updateRow(row)
Thanks
I think the easiest way would be to load the data into a list.
Note if you are working with a RDBMS the row order is not certain so this probably would not work unless you sorted by something.
eight_rows = []
k = 0
with arcpy.da.SearchCursor(targetFC, fieldnames) as rows:
for row in rows:
eight_rows.append(row)
k += 1
if k == 8: break
k = 5
with arcpy.da.UpdateCursor(targetFC, fieldnames) as rows:
for row in rows:
row = eight_rows[k]
k += 1
rows.updateRow(row)
if k == 8: break
Related
How in IBM ODM to iterate through each row of decision table column and insert each value of row into method for calculations and finally check which values returned by method is the smallest.
For example:
1. Step
For every row of column Bn where A = A1 do:
SomeMethod.calculate(B1) return C1 = 10;
SomeMethod.calculate(B2) return C2 = 40;
SomeMethod.calculate(B3) return C3 = 5;
2. Step
And get minimum of Cn values.
In my example it is 5.
Thanks in advance!
I have two arrays the first array is gulod_transaction and the second is gulod_medicine. I want to compare the two arrays with there id’s to minus the quantity from the medicine table to the quantity of transaction table. The main problem is when I add the second row first from table medicine to the transaction table. And click the Save Transaction button. In my console.log it’s minus the first row which is 40 from my first table to transaction table quantity which is equal to 10 and the result becomes 30. I want to minus both quantity if they have the same id’s.
for(let index = 0; index < this.gulod_transactions.length; index++) {
if (this.gulod_transactions[index].id === this.gulod_medicines[index].medicine_id) {
this.medicine_id = this.gulod_transactions[index].id;
this.medicine_name = this.gulod_transactions[index].name;
this.medicine_quantity = (parseInt(this.gulod_medicines[index].quantity) - parseInt(this.gulod_transactions[index].quantity));
this.medicine_price = this.gulod_transactions[index].price;
this.gulod_medicine_barangay_id = 1;
console.log(this.gulod_medicines[index].quantity);
console.log(this.gulod_transactions[index].quantity);
console.log(this.medicine_quantity);
}
}
This should be simple but I'm tearing my hair out trying to make it work:
I want to populate a grid with the values from an sqlite query.
rowNum = 3 # This is from a 'select count' query
row_num = range(rowNum) # This gives me [0, 1, 2]
tbl = [('apple', 'fruit'), ('bacon', 'meat'), ('rose', 'flower')] # from another query
for row in tbl:
cells = row[0:2]
for i in range(len(cells)):
self.mygrid.SetCellValue(row_num, i, str(cells[i]))
This tells me 'overload 1: argument 1 has unexpected type 'list'
for a in row_num:
for row in tbl:
cells = row[0:2]
for i in range(len(cells)):
self.mygrid.SetCellValue(row_num[a], i, str(cells[i]))
This populates three rows of the grid with 'rose' in col 1 and 'flower' in col2
I know this is a simple iteration problem but my mind doesn't see it.
In your first code block you do SetCellValue(row_num... where row_num is always [0, 1, 2].
In the second, you actually have 3 cycles, the innermost always writes all rows from tbl into the same row (row_num[a]), and the last one stays.
How about this:
for (row_idx, row) in enumerate(tbl):
for (col_idx, col) in enumerate(row[0:2]):
self.mygrid.SetCellValue(row_idx, col_idx, str(col))
I have an excel document with two sheets. Sheet 1 has columns A-Q and Sheet 2 has columns A-H. What I need is a code that will copy the information in a row from sheet 1 to sheet 2 if the criteria is met. The criteria is the word "Awarded" in column L (Sheet 1).
Also is it possible to have only specific columns in the row copied?
A B C D E F G H I J K L M N
X X Awarded X X
I would like to have only columns C,D,M, and N copied from the row if the word "awarded" is in column L. This information would be copied to Sheet 2 in the following fashion
Sheet 1 Sheet 2
D --> B
C --> C
M --> D
N --> F
I hope I'm being clear. Thanks in advance and let me know if I need to clarify!+
This is the code I currently have, which works. Only problem is it copies the entire row of information into sheet 2 when I only want rows D,C,M, and N to be copied.
Sub testing()
Set a = Sheets("Sheet1")
Set b = Sheets("Sheet2")
Dim d
Dim j
d = 1
j = 2
Do Until IsEmpty(a.Range("L" & j))
If a.Range("L" & j) = "Awarded" Then
d = d + 1
b.Rows(d).Value = a.Rows(j).Value
End If
j = j + 1
Loop
End Sub
First what you should do is change your data structure. Assuming you are using Excel 2007 or later, there is a great feature called Tables. If you highlight all of your data and go to Insert->Table, select the "My Table Has Headers" checkbox, and press ok, you will see a nicely formatted table. Do that for both of the data sets on each sheet.
This is more than just pretty formatting though, it is what is called a ListObject. In your VBA code, use the following to reference it:
Dim Table1 as ListObject, Table 2 as ListObject
Dim HeaderIndex as Integer
Dim MyColumnRange as Range
Set Table1 = Sheet1.ListObjects("TableName1")
`Change the table name under Formulas->Name Manager
Set Table2 = Sheet1.ListObjects("TableName2")
HeaderIndex = Application.WorksheetFunction.Match("ColumnLHeaderName", _
Table1.HeaderRowRange, 0)
Set MyColumnRange = Table1.ListColumns(HeaderIndex).DataBodyRange
MyColumnRange.Select
At this point, the select statement is just to show you what range you are dealing with now. The HeaderIndex refers to the header sub component of the table ListObject. Using Match() will allow you to specify the name of the column header without hard coding it's position. (i.e. if your data starts in column A, the header value in column L will return HeaderIndex = 12)
Now that you know what column you want, you select the ListColumn object. Then, the DataBodyRange is used to select the range component of that object. This is the entire range in that column. You can then iterate down the list to find the data you want.
EDIT: Updated Example:
'Specify your ranges you will be copying from beforehand, adding as many as you need here.
HeaderIndex_D = Application.WorksheetFunction.Match("ColumnXHeaderName", _
Table1.HeaderRowRange, 0)
HeaderIndex_C = Application.WorksheetFunction.Match("ColumnXHeaderName", _
Table1.HeaderRowRange, 0)
HeaderIndex_M = Application.WorksheetFunction.Match("ColumnXHeaderName", _
Table1.HeaderRowRange, 0)
HeaderIndex_N = Application.WorksheetFunction.Match("ColumnXHeaderName", _
Table1.HeaderRowRange, 0)
Set ColumnRange_D= Table1.ListColumns(HeaderIndex_D).DataBodyRange
Set ColumnRange_C= Table1.ListColumns(HeaderIndex_C).DataBodyRange
Set ColumnRange_M= Table1.ListColumns(HeaderIndex_M).DataBodyRange
Set ColumnRange_N= Table1.ListColumns(HeaderIndex_N).DataBodyRange
'Now, loop through each row that exists in your table. If the testing
'condition contained in MyColumnRange you previously defined is met,
'then assign the destination cell (which can be defined in the same way
'as above) equal to the lookup range's current row value (specified by i)
For i = 1 to MyColumnRange.Rows.Count
If MyColumnRange(i) = "Awarded" Then
DestinationCell1.Value = ColumnRange_D(i)
DestinationCell2.Value = ColumnRange_C(i)
DestinationCell3.Value = ColumnRange_M(i)
DestinationCell4.Value = ColumnRange_N(i)
End If
Next i
I am using PostgreSQL and let's say I have a tasks table to keep track of task items. Tasks table is as follows;
Id Name Index
7 name A 1
5 name B 2
6 name C 3
3 name D 4
Index column in tasks table stores the sort order of the tasks. Therefore I will output the tasks with respect to index in increasing order.
So When I change Task D(id = 3)' s index into 2 the new indexes should be as below;
Id Name Index
7 name A 1
5 name B 3
6 name C 4
3 name D 2
or when I change Task A(id = 7)' s index into 4 the new indexes should be as below;
Id Name Index
7 name A 4
5 name B 2
6 name C 3
3 name D 1
What I think is updating all row's index values one by one is pretty inefficient.
So what is the most efficient way to update all index values when I change one of the indexes in my Tasks table?
Edit :
First of all sorry for the confusion. What I am asking is not a simple exchanging two row indexes. If you look at the examples when I change Task D's index in to 2 more than one rows change. So when Task D is 2, Task B becomes 3 and Task C becomes 4.
For instance;
It is like when you drag Task D and drop below Task A so that it's index becomes 2 and B and C's index increases by 1.
SQL Fiddle
What you are doing is exchanging two row's indexes. So it is necessary to store the index value of the first updated one in a temp variable and setting it temporarily to a special value to avoid a unique index collision, that is, if the index is unique. If the index is not unique that step is unnecessary.
begin;
create temp table t as
select
(
select index
from tasks
where id = 3
) as index,
(
select id
from tasks
where index = 2
) as id
;
update tasks
set index = -1
where id = (select id from t)
;
update tasks
set index = 2
where id = 3
;
update tasks
set index = (select index from t)
where id = (select id from t)
;
drop table t;
commit;
The following assumes the index column (as well as id) is unique:
with swapped as (
select n1.id as id1,
n1.name as name1,
n1.index as index1,
n2.id as id2,
n2.name as name2,
n2.index as index2
from names n1
join names n2 on n2.index = 2 -- this is the value of the "new index"
where n1.id = 3 -- this is the id of the row where the index should be changed to the new value
)
update names as n
set index = case
when n.id = s.id1 then s.index2
when n.id = s.id2 then s.index1
end
from swapped s
where n.id in (s.id1, s.id2);
The CTE first creates a single row with the ids of the two rows to be swapped and then the update just compares the ids of the target table with those from the CTE, swapping the values.
SQLFiddle example: http://sqlfiddle.com/#!15/71dc2/1